هل هناك طريقة أكثر كفاءة لتشغيل الاستعلامات داخل حلقة؟ مشكلات الذاكرة

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

سؤال

لدي موقع ويب 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 ) 
) 

حيث كل صفيف داخلي هو عنصر واحد في العربة. إنها الكمية التي تسبب المشكلة ؛ عندما تكون منخفضة ، لا توجد مشكلة في تشغيل جميع الاستعلامات الإدراج وتحديث داخل الحلقة. ومع ذلك ، عندما تكون العناصر الكمية عالية ، أبدأ في الحصول على أخطاء تخصيص الذاكرة. هذا أمر مفهوم ، لأنه يدير بشكل أساسي عدة استعلامات مئات المرات. المشكلة هي أنه يمكن للمستخدم أن يطلب ألف بطاقة أو أكثر في وقت واحد (هذا برنامج حوافز الشركات) ، لذلك يجب أن أكون قادرًا على إدراج جميع السجلات وتحديثها ، بغض النظر عن حجم الكمية.

إليك الرمز ذي الصلة:

أولا ، الحلقة:

//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 أو نحو ذلك في وقت واحد ؛ بالنظر إلى متطلبات 1000+ ، فهذه مشكلة كبيرة. هذا هو الخطأ:

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 إلى القائمة مرة أخرى.

كما قال ألين أعلاه ، فأنت تضيف المتغير إلى نفسه بشكل كبير في كل مرة تعمل فيها الحلقة.

أعتقد أن هذا هو السبب في أنك تحصل على مشاكل الخطأ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top