1

私はSymfony2ベースのプロジェクトに取り組んでおり、cronタスクを使用して.csvドキュメントから150万の製品を定期的にインポートする必要があります。

現在、インポートは次のようになっています。

    ...

    Propel::disableInstancePooling();

    $fp = fopen($file, 'r');
    while ( !feof($fp) ) {
        $line = fgets($fp, 2048);
        $data = str_getcsv($line, "\t");

        $product = new Product();
        $product->setId($data[0]);
        $product->setTitle($data[1]);
        ...
        $product->save();
    }

    ...

ただし、約5分後、Apacheは512 MBのメモリ割り当てに達し、次のエラーをスローします。

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 78 bytes) in /var/www/vhosts/myapp.local/app/cache/dev/classes.php on line 9451

Propelのインスタンスプーリングを無効にしました(これは過去に他のフレームワークのPropelを利用したインポートで機能していました)が、まだ問題が発生しているので、Symfony 2が(スローされたエラーに基づいて)何らかのキャッシュを実行しているかどうか疑問に思っています)。

誰かが私を正しい方向に向けることができるSymfony2で大規模なインポートを実行した経験がありますか?

4

2 に答える 2

1

実際には、このインポートは、非常に複雑でない限り、mysql レベルで直接行う必要があります (mysql は csv ファイルからデータを読み取ることができます)。もう 1 つのアプローチは、ファイルをインクリメンタルに読み取り、SQL ファイルを生成し、その後ネイティブにデータベースにインポートすることです。メモリ不足になるため、このような大規模なインポートを Web アプリケーションで直接処理する理由はありません。

csv 全体を一度にメモリにロードしないように注意してください。

追加の解決策は、php.ini で php により多くのメモリを与えることです。PHP は、大量のデータをバッチ処理するのに最適な言語ではありません。

于 2012-12-27T19:37:30.473 に答える
1

ああ、私は6か月前のようにそこにいました。あなたに一言:トランザクション。

多かれ少なかれ10000行のパッケージのように、csvを断片に切り取り、パッケージごとに1つのトランザクションを実行します。これにより、dbに150万回書き込むオーバーヘッドを回避し、150のように書き込みます.

良い解決策をご案内できれば幸いです。時間を 30 秒から短縮することはできませんでした。この種の io/cpu バウンド タスクには、オフライン タスク プロセッサを検討する必要があるかもしれません。

現時点では、このページが私のバイブルでした: http://propelorm.org/documentation/06-transactions.html

編集

実際、これはサイトが必要とするある種のインポート アクションだと思いました。「開発者」が一度だけ行う必要がある場合は、Xnoise のアドバイスを使用します。

于 2012-12-27T19:30:36.650 に答える