2017-11-06 7 views
0

私は999,000レコードのリストデータを持っています。PHP - 大きなデータセットを処理するときに許容されるメモリを超過

データを取得するためにselectクエリとwhileループがあります。array_pushを使用して、取得した値を1つの配列にループで追加します。

そして、すべてのループがこの配列の1000個の値を処理するようにします。

ビッグデータと使用array_pushが、私はエラーを取得するときに私の問題がある:

Fatal Error: Allowed Memory Size of 134217728 Bytes

は、どのように私は私の問題を解決するために私のコードを最適化することができますか?

私のコードは以下の通りです:

$sql = "select customer_id"; 
$sql .= " from"; 
$sql .= " t_customer t1"; 
$sql .= " inner join t_mail_address t2 using(mid, customer_id)"; 
$result = $conn->query($sql); 
$customerArray = array(); 
while ($row = $result ->fetch(PDO::FETCH_ASSOC)) { 
    array_push($customerArray , $row); 
} 
// Execute every 1000 record 
foreach(array_chunk($customerArray , 1000) as $execCustomerArray) { 
    // My code to execute for every records. 
    // .... 
} 
+0

これらの〜1mレコードの各レコードが〜1kbのサイズであると仮定しましょう。それらは〜1GBのメモリといくつかのオーバーヘッドを消費します。通常は一度に多くのデータをメモリに保存する必要はありません。どうしてそんなことをする必要がありますか?一度に一つのレコードを処理しながら、データベースからフェッチする 'while'ループで処理します。 – deceze

+0

1000レコードごとに何かするつもりなら、whileループの中で1000をヒットしたかどうかチェックするだけでいいのですか? –

+0

取得する前にクエリ結果をチャンクする必要があります。後でない。 'LIMIT'と' OFFSET'を使用してページ単位の結果を取得し、必要なだけ多くのクエリを実行してください – apokryfos

答えて

1

私はそれが何を修正するかどうか不明だが、私は言うだろう一つのことは、配列にすべてのレコードをプッシュの使用は愚かである、です。

フェッチを使用して1つずつフェッチし、それらをすべてアレイに追加していますが、なぜ地球上でPDOStatement::fetchAll()を使用していないのですか?

例:

$sql = "select customer_id"; 
$sql .= " from"; 
$sql .= " t_customer t1"; 
$sql .= " inner join t_mail_address t2 using(mid, customer_id)"; 
$result = $conn->query($sql); 
$customerArray = $result->fetchAll(PDO::FETCH_ASSOC); 
// Execute every 1000 record 
foreach(array_chunk($customerArray , 1000) as $execCustomerArray) { 
    // My code to execute for every records. 
    // .... 
} 

我々は力仕事はすべての顧客レコードのためにあるものを見ることができないので、これは、あなたのメモリの問題を解決しないかもしれないが、私はあなたが持っていたループが愚かだったが、ほとんどのことを言うだろうあなたの記憶の問題の原因ではない可能性があります

これはスクリプトかウェブページのものかによって、インクリメンタルなループの並べ替えがあり、MySQL LIMIT function to implement basic paging for your dataを使用して、それがすべてメモリに入らないようにすることができますすぐに

+0

PDOStatement :: fetchAll()を使用すると多くのメモリが必要になります。 – user3363004

0

PDOStatement::fetchAll()を使用すると多くのメモリが必要になります。

私のコード編集は下記の意志の後:

$sql = "select customer_id"; 
$sql .= " from"; 
$sql .= " t_customer t1"; 
$sql .= " inner join t_mail_address t2 using(mid, customer_id)"; 
$result = $conn->query($sql); 
$customerArray = array(); 
while ($row = $result ->fetch(PDO::FETCH_ASSOC)) { 
    array_push($customerArray , $row); 

    // Execute every 1000 record 
    if (count($customerArray) == 1000) { 
     // My code to execute for every records. 
     // ... 
     $customerArray = array(); 
    } 
} 

しかし、配列$ customerArrayがデータを存在している場合、私は999.000レコードに最後の99件のレコードを実行する方法がわかりません。 私はパフォーマンスのために "select count"を使いたくありません。

+0

もう一度 'while'ループの後にもう一度コードを実行してください(あなたは' 'すべてのレコードに対して実行するコードです.'')。 –

+0

私はあなたの提案を知らない、より多くのデモを追加してください! – user3363004

関連する問題