ループ内でクエリを実行するためのより効率的な方法はありますか?メモリの問題

StackOverflow https://stackoverflow.com/questions/3856555

質問

カスタムショッピングカートコンポーネントを書いたJoomla Webサイトがあります。ユーザーは基本的にデータベースに保存している購入コードです。これらは印刷されたインセンティブカードに関連付けられています。ユーザーがチェックアウトしたら、データベースから一連のコードをつかみ(購入したことが多い)、コードのリストをループして、カート内の情報で他のテーブルを更新する必要があります。カートは、このようなセッション変数に配列の配列として保存されます。

$cart = Array ( 
[0] => Array ( [TypeFlag] => S [qty] => 25 [denom] => 50  [totalPrice] =>  100 )
[1] => Array ( [TypeFlag] => V [qty] => 10 [denom] => 25  [totalPrice] => 25 ) 
[2] => Array ( [TypeFlag] => C [qty] => 100 [denom] => 25  [totalPrice] => 25 ) 
) 

ここで、各内部配列はカート内の1つのラインアイテムです。問題を引き起こしているのは数量です。それらが低い場合、すべての挿入と更新クエリをループ内で実行するのに問題はありません。ただし、数量の要素が高い場合、メモリ割り当てエラーが発生し始めます。基本的に何百回もいくつかのクエリを実行しているため、これは理解できます。問題は、ユーザーが一度に1,000枚以上のカードを注文できる可能性があるため(これは企業のインセンティブプログラムです)、数量の大きさに関係なく、すべてのレコードを挿入および更新できる必要があることです。

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

まず、ループ:

//loop through vouchers to create purchase records, update voucher records, create certificates
$rightNow = date("YmdHis");
foreach($vouchers as $voucher) {
    $VoucherID = $voucher['VoucherID'];
    $VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];
    //create purchase record            
    $purchData = array("CcAuthCode"=>$ccAuthCode,"VoucherID"=>$VoucherID,"PurchAmt"=>$realFinalTotal, "ShipHandFee"=>number_format($shippingCharge,2),  "PurchDT"=>$rightNow,  "AcctID"=>$accountIDs['UserAcctID'], "ShipAddrID"=>$accountIDs['MailingAcctID']);
    $purchID = $model->createPurchaseRecord($purchData);    

    //update voucher
    $model->updateVoucherInfo($VoucherID,$accountIDs['BillingAcctID'], $denom, $purchID,$message);
}

実際のクエリは、モデル内のcreatepurchaserecordおよびupdatevoucherinfo機能内にあります。

function createPurchaseRecord($data){    
    $db =& JFactory::getDBO();
    $insFields = "";
    $valFields = "";

    foreach ($data as $f => $v){
        $insFields .= "," . $f;
        $valFields .= "," . $db->quote($v);
    }

    $insFields = substr($insFields,1);
    $valFields = substr($valFields,1);

    $query = "insert into arrc_PurchaseActivity ({$insFields}) values ({$valFields})";
    $db->setQuery($query);
    if (!$db->query()) error_log($db->stderr());

    return $db->insertid();
}

function updateVoucherInfo($voucherID,$billingAcctId, $balanceInit, $purchID, $certMessage) {
    //set ActivatedDT, BalanceInit
    $rightNow = date("YmdHis");
    $db =& JFactory::getDBO();
    $query = "UPDATE arrc_Voucher 
        set ActivatedDT=".$db->quote($rightNow).", BalanceInit=".$db->quote($balanceInit) . ", BalanceCurrent=".$db->quote($balanceInit).
    ", AcctID=".$db->quote($billingAcctId).", PurchActvtyID=".$db->quote($purchID) . ", certMessage=".$db->quote($certMessage)
    . " WHERE VoucherID=".$db->quote($voucherID);

    $db->setQuery($query);
    if (!$db->query()) error_log($db->stderr()); 
    $certificateNumber = $voucherID;
    return $certificateNumber;

}

誰かが私を助けることができますか?これをより効率的にする方法が必要です。今のところ、一度に30程度以上のことをしようとすると、メモリエラーが発生しています。 1,000歳以上の要件を考えると、これは大したことです。これはエラーです:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71303153 bytes) in /var/www/html/mysite.com/components/com_arrcard/controllers/checkout.php on line 110

行110は、上記のループからのこの行です。

   $VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];
役に立ちましたか?

解決

$VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];

あなたはこれを間違えています。リストをそれ自体に連結して、変数が指数関数的に増加します。

正しい方法:

$VoucherIDList .= "," . $voucher['VoucherNbr'];

また

$VoucherIDList = $VoucherIDList ."," . $voucher['VoucherNbr'];

よろしく、アリン

他のヒント

コードを少しきれいにし、不必要な呼び出しを排除するために。

それ以外の

foreach ($data as $f => $v){
    $insFields .= "," . $f;
    $valFields .= "," . $db->quote($v);
}

使用する

$valFields = implode(',', $data);
$insFields = implode(',', array_keys($data));

php.iniのメモリ使用量を増やします

PHP 5を使用している場合は、緩んでいます &.

配列の配列をループする代わりに。ロード $vouchers オブジェクトの配列として、オブジェクトは値ではなく参照によって渡されます。

foreach($vouchers as $voucher) {

$VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];

。=演算子であなたはの連結をしています $VoucherIDList それ自体。

上記の声明を使用すると、追加します $VoucherIDList もう一度リストに。

上記のAlinが言ったように、ループが実行されるたびに変数を指数関数的に追加しています。

これがあなたがエラーの問題を抱えている理由だと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top