私は、APIにヒットし、JSONファイル(オブジェクトの大きな配列)を受信してローカルに保存するcronスクリプトに取り組んでいます。それが完了すると、ダウンロードしたJSONファイルを別のスクリプトで解析し、各オブジェクトをMySQLデータベースに挿入する必要があります。
現在file_get_contents()
とjson_decode()
を使用しています。これは、ファイルを処理する前に、ファイル全体をメモリに読み取ろうとします。私のJSONファイルは通常250MB-1GB +の範囲であるという事実を除いて、これは問題ありません。 PHPメモリ制限を増やすことができることはわかっていますが、それが私の心の中で最大の答えであるとは思われません。fopen()
とfgets()
を使用してファイルを1行ずつ読み取りますが、jsonオブジェクトごとにファイルを読み取る必要があります。
オブジェクトごとにファイルを読み取る方法はありますか、または別の同様のアプローチはありますか?
これは、jsonファイルに何が含まれているかによります。
ファイルをワンショットでメモリに開くことができない場合、他の唯一のオプションは、ご存知のとおり、fopen/fgetsです。
行ごとの読み取りが可能であり、これらのjsonオブジェクトが一貫した構造を持っている場合は、ファイル内のjsonオブジェクトがいつ開始および終了するかを簡単に検出できます。
オブジェクト全体を収集したら、それをdbに挿入し、次のオブジェクトに進みます。
それ以上のことはありません。 jsonオブジェクトの開始と終了を検出するアルゴリズムは、データソースによっては複雑になる可能性がありますが、以前ははるかに複雑な構造(xml)でこのような処理を行ったため、問題なく動作しました。
このライブラリを試してください https://github.com/shevron/ext-jsonreader
PHP=に同梱されている既存のext/jsonは非常に便利で使いやすいですが、大量のJSONデータを扱う場合、JSONデータ全体をメモリに読み込む必要があるため、非効率的です(たとえば、file_get_contents()を使用して)PHP変数に一度に変換します-大きなデータセットの場合、これは大量のメモリを消費します。
JSONReaderはメモリ効率を考慮して設計されています-ストリームで機能し、データ全体をメモリにロードすることなく、任意のPHPストリームからJSONデータを読み取ることができます。また、開発者がJSONストリームから特定の値を抽出することもできます。すべてのデータをデコードしてメモリに読み込むことなく。
最善の解決策:
複数のリクエストにわたってデータを小さなチャンクで読み取ることができる、ある種の区切り文字(改ページ、タイムスタンプ、オブジェクトIDなど)を使用します。このソリューションでは、これらのJSONファイルの生成方法をある程度制御できると想定しています。私は次のことを前提にしています。
my JSONファイルは通常250MB-1GB +の範囲になるという事実を除いて、これは問題ありません。
1GBのJSONデータの読み取りと処理は、とんでもないことです。より良いアプローチが絶対に必要です。