Есть ли более эффективный способ запуска запросов внутри цикла? Вопросы памяти
-
27-09-2019 - |
Вопрос
У меня есть веб-сайт 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 )
)
где каждый внутренний массив - один элемент строки в корзине. Это кол-во, что вызывает проблему; Когда они низкие, нет проблем с выполнением всех запросов вставки и обновления внутри цикла. Однако, когда Elements Qty высоки, я начинаю получать ошибки распределения памяти. Это понятно, так как он в основном работает несколько запросов сотен раз. Выпуск в том, что пользователь может потенциально заказывать тысячу карт или более за раз (это корпоративная программа стимулирования), поэтому мне нужно иметь возможность получить все записи, вставленные и обновляемые, независимо от того, насколько велик.
Вот соответствующий код:
Сначала цикл:
//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);
}
Фактические запросы находятся внутри создателя CreatePourchereCord и 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
в список снова.
Как сказал Алин выше, вы добавляете переменную к себе экспоненциально каждый раз, когда цикл работает.
Я думаю, что именно поэтому вы получаете проблемы с ошибками.