2

アプリケーションにDoctrineとMongoDBを使用していますが、CSVファイルからコレクションにデータをインポートする必要があるタスクが1つあります。約5つの異なるCSVファイルがあり、ファイルごとに少なくとも450.000エントリがあり、1年に1〜3回重要です。

現在、ファイルのすべての行を繰り返し処理し、オブジェクトを作成し、persist()2.500アイテムごとに呼び出してフラッシュします。

各アイテムはそれほど大きくはなく、ID、10〜20文字の文字列、5〜10文字の文字列、およびブール値があります。

私の最初の質問は、5.000アイテムごとにフラッシュすると、挿入が大幅に遅くなることです。私のテスト環境では、5.000アイテムのフラッシュに約102秒かかり、2.500アイテムのフラッシュには約10秒かかりました。

しばらくするとフラッシングが遅くなります。前述のように、最初は2.500アイテムのフラッシュに約10秒かかりましたが、100.000アイテムの後、2.500アイテムのフラッシュには約1分かかります。

物事をスピードアップするために私ができる最適化はありますか?

4

2 に答える 2

3

スクリプトで最適化できる部分は2つあると思います。

  • CSVファイルの読み取り方法は、ロード方法に応じて、メモリに完全にロードするか(file_get_contents()またはfile()を使用して)、またはを使用してチャンクごとに読み取りfopen()ますfread()

最後のオプションは、一連の行を処理するときに必要な量のメモリしか使用しないため、推奨されます。

  • clear()すでに処理したオブジェクトを作成する必要があります。そうしないと、スクリプトが終了するまでメモリに保持されます。これは、1つのDC2オブジェクトが1Moのメモリを使用し、100,000のオブジェクトがある場合、スクリプトの最後に100,000Moを使用することを意味します。したがって、挿入を2,500の範囲でバッチ処理することは非常に良い考えですが、処理されたオブジェクトをEntityManagerから削除する必要があることは明らかです。

それはを使用して行うことができます$entityManager->clear();

clear()全体をクリアします。単一のEntityManagerエンティティをクリアしたい場合は、を使用できます$entityManager->detach($object)


メモリ使用量をプロファイリングしたい場合は、関数にも興味があるかもしれません

memory_get_usage()

memory_get_peak_usage()

于 2012-10-18T15:17:48.480 に答える
1

このインポートスクリプトがDoctrineODMを使用する必要がある理由はありますか?アプリケーション全体としては、確かに。ただし、PHPは大きなコレクションの保持と処理においてそれほど効率的ではないため、大量のデータを大量のオーバーヘッドで処理することは最適ではありません。

実行できる最善の最適化は、そのレイヤーをスキップしてmongodbクラスを直接使用し、ファイルを一度にすべてではなく1行ずつ読み取るようにすることです。また、BatchInsert()を使用すると、MongoDBへのネットワーク遅延がある場合に大幅に高速化されます(ただし、5kドキュメントにプッシュする必要はありません)。

于 2012-10-18T13:05:28.450 に答える