1

MySqlで毎日更新〜10.000アイテムが必要です。CSV ファイルをアップロードして、データベース データを更新しようとしました。私は2つのフィールドで分岐しています。私の問題は機能しますが、しばらくすると 504 Gateway Time-out が発生し、アップロードがプロセスを完了できないことです。

ここに私のコードがあります

if(is_uploaded_file($_FILES["filename"]["tmp_name"])){
        //      
        move_uploaded_file($_FILES["filename"]["tmp_name"], "".$_SERVER["DOCUMENT_ROOT"]."/upload/".$_FILES["filename"]["name"]);
    $file_path="".$_SERVER["DOCUMENT_ROOT"]."/upload/".$_FILES["filename"]["name"]."";

    $file=file_get_contents("".$file_path."");
    $file=iconv("windows-1251", "utf-8",$file);
    file_put_contents("".$file_path."",$file);

if(!setlocale(LC_ALL, 'ru_RU.utf8')) setlocale(LC_ALL, 'en_US.utf8'); if(setlocale(LC_ALL, 0) == 'C') die('       (ru_RU.utf8, en_US.utf8)');
    if (($handle_f = fopen($file_path, "r")) !== FALSE) { 
        //   csv
        while (($data_f = fgetcsv($handle_f,99999,";"))!== FALSE) {
            //   ean13 
            $sql="SELECT id_product FROM ps_product WHERE reference = '".$data_f[0]."'";
            $id_product = Db::getInstance()->getValue($sql,0);  

            //   ,    
            if ($id_product) {      
                $sql=mysql_query("UPDATE `ps_product` SET `quantity` ='".$data_f[1]."' WHERE `reference`='".$data_f[0]."'");
                echo "<p style='color:green'>Items<b>".$data_f[0]."</b> updated</p>";
            } else{
                echo "<p style='color:red  '>Items<b>".$data_f[0]."</b> not found</p>";
            }
        }
      echo "<b>Update is complited</b>";  

    }else{
        echo "Can`t open imported file";
    }
}else{
    echo '
    <h2>Quantity update:</h2>
    <form action="'.$_SERVER["PHP_SELF"].'" method="post" enctype="multipart/form-data">
              <input type="file" name="filename"><br>
              <input type="submit" value="Load"><br>
    </form>
    ';
}

現在、失敗ごとに最大 1000 個のファイルを Excel で分割し、データベースを更新しています。時間がかかります。アイデアを教えてもらえますか、それともコードにエラーがあるのでしょうか? 役に立たないと思うので、ajaxを使用して更新します。

4

3 に答える 3

0

大きな CSV を MySQL にロードする必要がありましたが、生の CSV データを保持できるテーブルを作成することが最善の解決策であることがわかりました。CSV と同じフィールドを持つテーブルを作成し、を使用して一括インポートをLOAD DATA実行します。これは高速であり、SQL を使用してデータに対して必要なクエリを実行できます。

LOAD DATA LOCAL INFILE '{$filename}' 
INTO TABLE {$table_name} 
FIELDS TERMINATED BY '|' 
LINES TERMINATED BY '\n' 

テーブルに CSV データを取得したら、クエリをブロック (LIMIT および OFFSET) で実行するだけで、疑似コードなどを実行できます。

DEFINE("BLOCK_SIZE",100);

// Get the total rows in CSV table so when can divide into blocks
SELECT SQL_CALC_FOUND_ROWS  * 
FROM   my_csv_table
LIMIT  1;

$total_rows = SELECT FOUND_ROWS();

for($counter = 0; $counter < $total_rows; $counter += BLOCK_SIZE)
{

    SELECT * 
    FROM   my_csv_table
    LIMIT  BLOCK_SIZE
    OFFSET $loop_counter;

    foreach $row 
    {

        // UPDATE YOUR REAL TABLE IF MATCHED

    }

}
于 2012-08-24T09:25:29.270 に答える
0

参考になる索引はありますか?そうしないと、更新ごとに時間がかかります。

また、いくつかの主要な SQL インジェクションの問題があり、mysql が減価償却され、mysqli に切り替えます。

于 2012-08-24T07:06:21.660 に答える
0

504 Bad Gateway Timeouttimely responseゲートウェイ/プロキシ サーバーが処理サーバーから を取得しなかった場合です。このような場合、処理サーバーがすべての更新を終了しても、処理がまだ進行中であることを知らせるメッセージをプロキシに送信しなかったため、プロキシは接続を閉じます。

この場合、更新に ajax を使用することはあまり良い考えではありません。ただし、あなたを助けることができるajax design patternと呼ばれるものがあります。heartbeat pattern基本的な考え方は次のとおりです。

  1. 処理ページに通常の呼び出しを行い、CSV 更新を開始します
  2. さらに、X分ごとにサーバーページへのajax呼び出しを行うJavaScriptタイマーをページに設定します
  3. サーバーは単純なメッセージで応答します。1文字でも構いません
  4. クライアント側の ajax は、このメッセージを無視したり、出力したりできます。
  5. X 分後、同じプロセスが発生します。
  6. その間、ステップ 1 で開始した CSV 処理は引き続き続行されます。

これcontinuous message request and responseは と呼ばれheartbeatます。connection aliveサーバー処理が行われている間、それを維持するのに役立ちます. サーバーの処理が終了して確認が得られたら、必要に応じてタイマーを強制終了し、接続を閉じることができます。

もちろん、処理サーバー側ではincrease timeout lenghtadd database indexesなどを追加して、php process timeoutが発生しないようにすることができます。

ただし、プロセスのタイムアウトはゲートウェイのタイムアウトとは異なることに注意してください。

于 2012-08-24T07:13:10.843 に答える