繁体   English   中英

有没有在循环内运行查询的更有效方法? 记忆问题

[英]Is there a more efficient way to run queries inside a loop? Memory issues

我有一个Joomla网站,我为此编写了一个自定义购物车组件。 用户基本上是在购买我们存储在数据库中的代码-这些代码与印刷的激励卡相关联。 当用户签出时,我需要从数据库中获取一大堆代码(无论他们购买了多少代码),然后遍历代码列表并使用购物车中的信息更新其他表。 购物车以数组数组形式存储在会话变量中,如下所示:

$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 ) 
) 

其中每个内部数组都是购物车中的一个订单项。 导致问题的数量是多少; 当它们低时,在循环内运行所有插入和更新查询就没有问题。 但是,当数量元素很高时,我开始遇到内存分配错误。 这是可以理解的,因为它基本上运行了数百次查询。 问题是,用户一次可能订购1000张或更多张卡(这是一项公司奖励计划),因此,无论数量多大,我都需要能够插入和更新所有记录。

以下是相关代码:

首先,循环:

//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加载$vouchers对象数组,对象通过引用而不是通过值传递。

foreach($vouchers as $voucher) {

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

使用。=运算符,您正在将$VoucherIDList自身串联。

使用上面的语句,您还可以再次将$VoucherIDList添加到列表中。

就像上面的Alin所说,每次循环运行时,您都在将变量成指数增加。

我想这就是您遇到错误问题的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM