3

少し奇妙な問題に遭遇しました。こんなふうになります。クライアントに出力する必要がある大量のデータがあります。これらのデータ ファイルは事前に作成することはできず、ライブ データから提供する必要があります。

私の推奨する解決策は、次のようにフェッチから行ごとに CSV に書き込むことです。

 while($datum = $data->fetch(PDO::FETCH_ASSOC)) {
            $size += fputcsv($outstream, $datum, chr(9), chr(0));
 }

これにより、多くのばかげたメモリ使用量が回避されました (一度に 100000 レコードをメモリに読み込むのはよくありません) が、データのサイズが大きくなるにつれて悪化するだけの大きなテーブルの問題がまだ残っています。また、データのパーティショニングがないことに注意してください。年単位でダウンロードするのではなく、すべてのデータをダウンロードしてから、自分でセグメント化します。これは要件ごとです。私はこれを変更して問題を完全に取り除く立場にはありません。

どちらの場合も、最大のテーブルではメモリが不足します。解決策の 1 つは、使用可能なメモリを増やすことです。これにより 1 つの問題は解決しますが、後で、または複数のクライアントがダウンロードしている場合に、サーバーの負荷の問題が発生する可能性があります。

この場合、$outstream は次のとおりです。

$outstream = fopen("php://output",'w');

これは明らかに物理的なディスクの場所ではないようです。クライアントに送信される前にデータが存在する場所に関して php://output についてはあまり知りませんが、このメソッドを介してマニホールド データベース テーブルを csv に書き込むだけでメモリの問題があることは明らかです。

正確には、ステージング ボックスは PHP に約 128 MB を許可し、特にこの呼び出しは約 40 MB と短かったです (さらに 40 MB を割り当てようとしました)。部品。

これを処理するために何ができるか知っている人はいますか?

4

1 に答える 1

2

したがって、メモリ消費はZendFrameworkの出力バッファリングが原因であるように見えます。私が思いついた最善の解決策はこれでした。

ファイルをクライアントにストリーミングし始める直前にob_end_clean()を実行します。ZFのこの特定のインスタンスは、この時点以降、通常の出力を生成したり、それ以上のことを実行したりすることはないため、問題は発生しません。(おそらくユーザーの観点から)奇妙なことが起こるのは、ファイルが実際にストリーミングされることです。

コードは次のとおりです。

ob_end_clean();
while($datum = $data->fetch(PDO::FETCH_ASSOC)) {
            $size += fputcsv($outstream, $datum, chr(9), chr(0));
}

メモリ使用量(ZFフォーラムの投稿で提案されている関数memory_get_peak_usage(true)による)は90メガバイトから9メガバイトになりました。これは、ファイルを読み取る前に開発ボックスで使用していたものです。

助けてくれてありがとう、みんな!

于 2012-06-27T15:10:24.447 に答える