2016-10-08 19 views
1

私はデータセットにロードするJSONファイルを生成します。これらのJSONファイルには、データベースの何千もの行が含まれます。これらを生成するには、データベースのすべての行をループし、各データベース行をJSONファイルの新しい行として追加する必要があります。私はに実行している問題は、このです:私がやっている何PHP - JSONファイルに追加する方法

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262643 bytes)

、私はその後、私は配列に新しい行を追加するのfile_get_contents($ json_file)とJSONファイルを取得し、配列にそれをデコードしています配列をJSONにエンコードし、file_put_contents($ json_file)でファイルにエクスポートします。

これを行うより良い方法はありますか?各ループ反復でメモリが増えるのを防ぐ方法がありますか?それとも限界に達する前に記憶をクリアする方法はありますか?私はスクリプトを完了するまで実行する必要がありますが、このメモリの問題では、クラッシュする前に5%の完了を達成することはほとんどありません。

スクリプトを再実行して再実行するとJSONファイルに行が追加されるため、このメモリの問題が避けられない場合は、スクリプトが完了するまで自動的にスクリプトを何度も再実行する方法がありますか?たとえば、私はメモリの使用量を検出し、その限界に近づいてからスクリプトを終了して再起動することを検出できますか?私は熟しているので、exec()のようなセキュリティ上の危険な機能を許可しません。

+1

最初に質問したのは、メモリー、DB、ファイルサイズ、配列サイズなどを実行していることです。128Mを使用しているのは、まともなサーバー上で約512Mまでかなり安全です。しかし、それは実際の問題が何であるかに応じて短期的な解決策になるかもしれません。 – ArtisticPhoenix

+0

ファイルが1つの大きなJson配列であるのか、複数のjson配列が1つのファイルにあるのかは疑問ではありません。私は 'file_put_contents'のために1つを仮定しますか? – ArtisticPhoenix

+0

jsonの問題は、完全なオブジェクトをメモリに持たなければならないということです.CSVを使用することができれば、このような問題は起こりません。コンテンツを読み込まなくても行を追加することもできます。しかし、ネストされたデータがあり、すべての行(ヘッダー)に同じスキーマがあります。 CSVファイルを読み込んで一度に1行ずつ書き込むことができます。ファイルサイズでOSの整数制限を上げることができます。私は個人的に1000万行を超えるファイルを作成しました。あなたが何であるかを知らなければ、それはちょうどカンマで区切られたリストで、ヘッダー行が付いています。 – ArtisticPhoenix

答えて

0

個人的に私がコメントで述べたように、私はCSVファイルを使用します。彼らはいくつかの利点があります。

  • あなたは唯一のあなただけのファイルに新しいデータを追加することができ一行
  • ためのメモリを管理するように、一度に1行を書く/読むことができます。
  • PHPには、fputcsv()またはSPLファイルオブジェクトのいずれかを使用して、豊富なサポートが組み込まれています。
  • ファイル全体を通じて同じスキーマを保つ唯一の短所は

    • をしている「データINFILEのロード」

    http://dev.mysql.com/doc/refman/5.7/en/load-data.html

    を使用して使用してデータベースにそれらを直接読み込むことができ

  • ネストされたデータ構造体なし

Jsonの問題は(私が知る限りは)全体を1つのデータセットとしてメモリに保存しなければならないことです。そのため、通常のテキストファイルのように(行のための行)ストリームすることはできません。 jsonデータのサイズを制限する以外には、実際には簡単ではない可能性があります。いくつかのメモリを増やすことはできますが、データが拡大し続けることが予想される場合は、一時的な修正に過ぎません。

私たちは運用環境でCSVファイルを使用しています。私は定期的に800kまたは1M行のデータセットを扱います。私は10M行のものも見たことがあります。私たちは、CSVアップロードから読み込まれる60M行(MySql)の単一のテーブルを持っています。そうすれば、うまくいくでしょう。

あなたがJsonで設定した場合は、固定された数の行があり、一度に複数の行だけを実行するようにコードを設計します。それ以上のことをすることなく私はそれをする方法を推測することは不可能です。

+0

CSVファイルを使用するつもりでしたが、コンテンツにカンマが表示され、CSV構造が破損する可能性があると心配しました。 2番目の考えでは、コンマが表示される理由がないので、CSVファイルに切り替える予定です。 –

+0

おっと、私はあなたのことを間違って読んでいました。私はあなたがCSVファイルをJQueryのデータ型にロードできると言ったと思いました。私はそれが難しいとは確信していませんが、JSONを使ってJSONファイルをそのままAJAXリクエストでロードします。 –

+0

ああ、私はあなたがデータベースを言っていると思った。限り、コンマに行くそれはphpの問題ではないとfputcsvとSPLファイルのオブジェクトハンドルは自動的にエスケープします。私が今まで問題になっていた唯一の事は、データ\ 'バックスラッシュの引用符であり、実際の入力は '\\'で終わっていて、空白またはカンマのいずれかを持っていたと思います。空白とカンマを二重引用符で囲んでいます。つまり、終わりのバックスラッシュでは、引用符で囲まれたphpをエスケープします。 – ArtisticPhoenix

0

CSVファイルを使用するように切り替えて、メモリの問題を解決しました。スクリプトも非常に高速に実行されます。jQueryのDataTableのは、CSVファイルのサポートが組み込まれていないので、私はJSONにCSVファイルを変換する関数を書いた:

public function csv_to_json($post_type) { 

     $data = array(
      "recordsTotal" => $this->num_rows, 
      "recordsFiltered" => $this->num_rows, 
      "data"=>array() 
     ); 

     if (($handle = fopen($this->csv_file, 'r')) === false) { 
      die('Error opening file'); 
     } 

     $headers = fgetcsv($handle, 1024, "\t"); 
     $complete = array(); 

     while ($row = fgetcsv($handle, 1024, "\t")) { 
      $complete[] = array_combine($headers, $row); 
     } 

     fclose($handle); 

     $data['data'] = $complete; 

     file_put_contents($this->json_file,json_encode($data,JSON_PRETTY_PRINT)); 

    } 

だから、結果は私がはるかに速く作成するよりも、CSVファイルやJSONファイルを作成していますJSONファイルだけで、メモリ制限に問題はありません。

関連する問題