2012-03-07 10 views
0

私はjsonデータをmysql.My jsonファイルに3.7Mb近づけようとしていますが、17k行(テストデータの実際のデータは65k行になります)です。スクリプトは非常に遅く、ほぼ8〜9分です。そこにPHPの進捗インターフェイスでmysqlにjsonデータをインポートするための速い方法はありますか? そして、私はプログレスバーの機能とその作品を今のところ追加しようとしています。大きなJsonデータをmysql

$veri=json_decode(file_get_contents('auctions.json')); 

      $sayi=count($veri->alliance->auctions); 
      $a=$veri->alliance->auctions; 
      $yuzde=round($sayi/100); 
      echo "<div id='tasiyici'>"; 
      $sql=$db->prepare("INSERT INTO auctions (id, auc, item, owner, bid, buyout, quantity, timeLeft) VALUES ('',?,?,?,?,?,?,?)"); 
      for ($i=0;$i<=$sayi;$i++){ 
       $sql->execute(array($a[$i]->auc,$a[$i]->item,$a[$i]->owner,$a[$i]->bid,$a[$i]->buyout,$a[$i]->quantity,$a[$i]->timeLeft)); 
       if($i%$yuzde=='0'){ 
        $y=$i/$yuzde; 

        if(($y*4+4)>"180"){$pos=40-(($y*4+4)-180); $color="color:#fff";} 
        if(($y*4+4)>=220){$pos=0;} 
        echo "<div class='rakam' style='background-position:-".$pos."px 0;".$color."'>%".($y+1)."</div>"; 
        echo "<div class='yuzde' style='width:".($y*4+4)."px;'></div>"; 
        ob_flush(); 
        flush(); 

       } 


      } 
      echo "</div>"; 

      echo "<br> $sayi data added."; 

CSSコード

<style> 
     body { 
      font-family:Arial; 
     } 
      #tasiyici { 
       width:400px; 
       height:17px; 
       display: block; 
       position: relative; 
       margin:50px auto; 
       background:#e3e3e3; 
       border-radius:5px; 
       overflow: hidden; 
       border:1px solid #ccc; 
      } 
      .yuzde { 
       height:17px; 
       display: block; 
       width:1px; 
       background:url("progressOverlay.png"); 
       position: absolute; 
       top:0; 
       left:0; 
       z-index:1; 
      } 
      .rakam { 
       width:40px; 
       height:16px; 
       display: block; 
       line-height:17px; 
       position: absolute; 
       left:50%; 
       top:0; 
       margin-left:-20px; 
       z-index:9999; 
       background:url("progressOverlay.png") -40px 0 #e3e3e3 no-repeat; 
       font-size:11px; 
      } 

     </style> 
+1

実行ごとに複数の行を挿入できますが、準備された文と大きく異なる場合は懐疑的です。私はあなたのデータの少なくとも1%を実行ごとに挿入しようとします。 INSERT INTOを再利用することは、あなたのボトルネックがデータの量であるので大きな違いはありません。もう1つの方法は、JSONデータを変換し、http://stackoverflow.com/questions/2811096/mysql-bulk-insert-from-csv-data-files – Basti

+2

のように一括インポートすることです。「$ sayi」は65,000になる可能性がありますか?それが事実なら、実行中のクエリは65,000件になります。代わりに、100または1,000のバッチでクエリを実行してみてください。私は準備/実行でそれを行う方法がわかりませんが、 'テーブル(キー)の値(値)、(値)、(値)...などに挿入し、あなたが100か1000か何かを得てからそれを実行するまで)より少ないmysql接続があるので(あなたの設定に応じて)少し速くなければなりません。 1000のバッチは65のクエリにそれを切り捨てます – Benno

+1

ありがとう皆私は1つのクエリのために1000行を試してみます。私は結果をここに追加します。 – xuma

答えて

1

9分毎秒* 60秒= 540秒

540分の17000 =〜30.5を記録MySQLのmanページへのリンクです残念なことに、特定の時点で問題を直接置くことはできません。とにかく30.5インサート/秒は、深刻なサーバーではあまりありません。あなたの列のサイズが大きく見えないので、確かに非常に実用的です。

あなたがする必要があるのは、重大な測定を行うことです。たとえば、メモリサイズが不足すると問題が発生します。また、テーブル上の高価なインデックスの多くは、挿入をかなり難しくします。

これを何度も(ユーザーのアップロードなどで)行うと、時間がかかりますので、キューを作成することをお勧めします。 17kのインサートは分単位で行うことができます。挿入のためのMySQLの最適化について可能なドキュメントがたくさんある

が、これは速度で影響の一般的な概要です:あなたのスクリプトではないようです一見http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

、それは本当にありません特別。だから、データをアップロードし、それを保存し、バックグラウンド・プロセスが処理する、cronのように、バックグラウンドで実行中のプロセスに一定の実行中のスクリプトなどを挿入ハンドル

  1. :私は2つのスクリプトでプロセスを区切るだろうけどそれ。おそらくそれのためのテーブルimportjobsを作成します。

すべてのXレコードは、あなたがこのような何かを行うことができます:

UPDATE importjobs SET counter = :amountimported WHERE id=:jobid 
  1. あなたは状況に答える与えるスクリプト。バックグラウンドスクリプトによって書かれたステータスメッセージを得ることによって。

    importjobs ID = FROM partdone、カウンタ、トータルAS SELECTカウンタ/トータル:ジョブID

ユーザーインターフェイスから完全に別々のプロセスを測定し、改善することができますこの方法に。懸念の分離が起こる。インポートには最高のスピードをあげ、プロセスから更新インジケータを完全に分離することができます。

速度に応じて、5秒、10秒、20秒、60秒などのどれかを更新するかどうかを決めることができます。このルックアップは非常に安いので、あなたはそれを何度か行うことができます。ほとんどの場合、importjobsテーブルも非常に小さいためです。

+0

申し訳ありませんが情報が不足しています。現地で作業しており、正確な時刻は8〜9分ではありません。現在、私はapiからjsonデータを取得しようとしています(http://eu.battle.net/auction-data/veknilash/auctions.json )、json fileとして保存してください.Sqlファイルを読み込んで生成すると、mysqlにロードしようとします(まだ成功していません)。それを行うには本当の方法ですか、それとも他のロジックが必要ですか?私がこの部分で成功することができるなら、私は進歩情報でそれをやろうとします。 – xuma

+0

それは大丈夫です、ちょうどあなたが測定する方法を示しています。たとえば、スピードを示すためにたくさんの行を挿入する単純なスクリプトを書くことができます。一般的に、開発マシンでは、本番環境で使用する最適化されたサーバーと比較してパフォーマンスがはるかに低くなっています。まずコードを測定し、そうでなければ間違ったことに多くの時間を費やすかもしれません。 –

0

拡張インサートは、まだは、LOAD DATA INFILEを使用してみてください十分に速くはない場合。それはあなたに進歩を与えることはありませんが、あなたが知っている最速のデータをロードします。

を挿入するときに、あなたがしたので

編集はここhttp://dev.mysql.com/doc/refman/5.1/en/load-data.html

+0

ありがとうございました。私はおそらくそれを今使っています。でも、まだ私はプログレスを見たいです。 – xuma

1

私は同様の問題を解決する必要がありましたが、外部APIからのレコード数はわかりませんでした。私の仕事はちょうど途中に落ちる危険性があり、私は再び始める必要はないと気づきました。

あなたの問題はその点で似ています。データベースに依頼するのは、レコードがすでに存在する場合でもレコードを挿入することです。それは高価です。

私がやったのは、データのキーや独自の識別情報を格納したコントロールテーブルを構築することでした。処理中、ジョブは制御データベースを読み取ってレコードが存在するかどうかを判断し、存在する場合は次のレコードにスキップします。

私はロードをテストすることができるレコード番号リミッタを作成しました(最初の100レコードに制限します)。このツールを使用すると、ブラウザの5つの開いたタブでphpスクリプトを実行して、 。