2011-01-01 11 views
4

私は5,000の結果セットに対して次のコードを実行しています。メモリが使い尽くされて失敗しています。何千ものレコードを実行しているときにPHPメモリが枯渇しました

foreach ($data as $key => $report) { 
    $data[$key]['data'] = unserialize($report['serialized_values']); 
} 

メモリ制限を超えることはできますが、代わりに問題なく実行したいと思います。私は記憶を永遠に引き上げることはできないだろう。


EDIT

$dataこの形式である:

[1] => Array 
    (
     [0] => 127654619178790249 
     [report_id] => 127654619178790249 
     [1] => 1 
     [user_id] => 1 
     [2] => 2010-12-31 19:43:24 
     [sent_on] => 2010-12-31 19:43:24 
     [3] => 
     [fax_trans_id] => 
     [4] => 1234567890 
     [fax_to_nums] => 1234567890 
     [5] => ' long html string here', 
     [html_content] => 'long html string here', 
     [6] => 'serialization_string_here', 
     [serialized_values] => 'serialization_string_here', 
     [7] => 70 
     [id] => 70 
    ) 

答えて

10

forとforeachの問題以外にも、ソリューションを再構築する必要があります。正当にあまりにも多くのメモリを使用しているため、メモリの制限にぶつかっています。データベース列の内容をアンシリアライズし、アレイ

$data[$key]['data'] 

に格納するたびにPHPは、それが後でアクセスできるようにデータを格納するメモリのチャンクを取っておく必要があります。配列が大きすぎるとメモリが不足します。プレーン・イングリッシュで、あなたはPHPを教えています

すべての5000行のデータを取り込み、それらをメモリに格納します。後でそれらを使って何かを行います。

問題に近づくには、別の方法を考える必要があります。以下の項目は、この問題に関する2つの簡単な考えです。

あなたは、メモリ内の項目を格納し、ちょうどあなたがループにしたかったどんな行動取る、あなたはまた、唯一のあなたから必要な情報を格納することができ

foreach ($data as $key => $report) { 
    $object = unserialize($report['serialized_values']);   
    //do stuff with $object here 
} 

なる必要があるとして、PHPはアイテムを破棄することができませんでしたあなたが実際にあまりにも多くのメモリを使用しているので、あなたは、メモリの制限をヒットしている:むしろ

foreach ($data as $key => $report) { 
    $object    = unserialize($report['serialized_values']);   
    $data    = array(); 
    $data['foo']  = $object->foo; 
    $data[$key]['data'] = $data; 
} 

かいつまんでオブジェクト全体を保存するよりも、シリアライズオブジェクト、。ここには魔法の解決策はありません。シリアライズされたデータを格納し、すべてを単一のプログラムにロードしようとすると、言語/プラットフォームに関係なく、メモリ集中型のアプローチになります。

+0

すばらしい説明。これが起こったときに99%の時間がコーディングエラーであったので、実際に私にメモリが足りなくなっているということを実際に教えてくれていいですね。私はコードをリファクタリングして、一度に5000行すべてを処理しなかった。助けてくれてありがとう、アラン! –

3

foreachメモリに全て5,000結果をロードします。多数の苦情をthe docsでご覧ください。 forループを使用し、必要に応じて各結果にアクセスします。

+0

良い考えですが、' foreach'ではなく 'for'でメモリエラーが発生しています。うーん... –

+0

@ジェームズとループを削除する場合は?それは犯人ではないかもしれない。 – marcog

+0

また、 'unserialize'すると' $ report'の値を 'unset 'するのは意味がありますか?言い換えれば、処理した後に '$ data'にある個々のエントリによって使用されるメモリを解放してください。これを*ループ内で*行います。 – marcog

0

これは代わりに値をコピーするの参照を代入します

foreach ($data as $key => &$report) { 
} 

この方法を試してみてください。

+0

応答Fivellをありがとうが、それでもエラーをスローしています。 –

+0

データ要素の構造は何ですか? – Fivell

+0

投稿のデータ構造を編集しました。 –

0

これは実際に多くのサイトが結果をページで分割する理由です。

私は5000の結果があるとします(簡略化するために、ユーザーと言うと)、これらの5000の結果をすべて表示するページがあります。私は5000ページの結果を500ページに分け、ページ1は1〜500、ページ2は501〜1000、ページ3は1001〜1500などを表示します。このようにして、メモリが節約される。

5000ページの結果をすべて1ページに表示する必要がある場合は、実際にはメモリの容量を増やす必要があります。代わりにforループを使用してください。

0

私は確かに知りませんが、あなたは使用することがあります:

  • gzip($データセット)安全なメモリにデータを圧縮し、その場でそれを収縮させます。
  • 制限(データ)が設定されています。
  • システムのようなキャッシュを作成します。あまりにも多くのメモリを使用する場合、キャッシュからLRU(least recently used)データを削除します。
1

$dataとは何ですか。どこから取得していますか?ファイルの場合は、一度に1行ずつ解析してfgets()することはできません。また、データベースであれば、一度に1つのレコードを処理することはできません(MySQLが結果セットを閉じるのを待っています) 。私は$dataの全体をすぐにメモリにロードし直してから、それをループすることを再検討すべきだと思います。

関連する問題