Y at-il un moyen plus efficace pour exécuter des requêtes dans une boucle? Problèmes de mémoire

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

Question

J'ai un site Joomla que j'ai écrit un shopping personnalisé panier composant pour. L'utilisateur est essentiellement des codes achetant nous nous stockons dans notre base de données - celles-ci sont associés à une carte imprimée incitation. Lorsque les contrôles utilisateur, je besoin de saisir un morceau de code à partir de la base de données (mais beaucoup qu'ils ont acheté), puis une boucle sur la liste des codes et mettre à jour d'autres tables avec des informations dans mon panier. Le panier est stocké sous la forme d'un tableau de tableaux dans une variable de session, comme ceci:

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

où chaque réseau interne est une ligne de commande dans le panier. Il est le qté qui est l'origine du problème; quand ils sont bas il n'y a pas de problème en cours d'exécution toutes les requêtes d'insertion et de mise à jour dans la boucle. Cependant, lorsque les éléments de qté sont élevés, je commence à obtenir des erreurs d'allocation de mémoire. Cela est compréhensible, car il est essentiellement l'exécution de plusieurs requêtes des centaines de fois. La question est, un utilisateur pourrait commander un millier de cartes ou plus à la fois (ce qui est un programme d'encouragement de l'entreprise), donc je dois être en mesure d'obtenir tous les enregistrements insérés et mis à jour, quelle que soit la taille de la qté est.

Voici le code correspondant:

Tout d'abord, la boucle:

//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);
}

Les requêtes réelles sont à l'intérieur des fonctions createPurchaseRecord et updateVoucherInfo dans le modèle:

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;

}

aide quelqu'un peut me sortir? Il doit y avoir un moyen de rendre plus efficace; Actuellement, il est de lancer une erreur de mémoire lorsque je tente de faire plus de 30 ou à un moment; compte tenu de l'exigence de 1,000+, c'est une grosse affaire. Ceci est l'erreur:

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

Ligne 110 est la ligne de la boucle ci-dessus:

   $VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];
Était-ce utile?

La solution

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

Vous faites ce mal. Vous concaténer la liste se traduit par la variable croissance exponentielle.

Manière correcte:

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

ou

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

Cordialement, Alin

Autres conseils

Pour rendre votre petit code plus propre et d'éliminer les appels inutiles.

Au lieu de

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

Utilisez

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

Augmentation de l'utilisation de la mémoire php.ini

Si vous utilisez PHP 5, & lâche.

Au lieu de bouclage tableau de tableaux. $vouchers de charge en tant que tableau d'objets, les objets sont passés par référence plutôt que par valeur.

foreach($vouchers as $voucher) {

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

Avec le. = Opérateur que vous faites une concaténation de $VoucherIDList à lui-même.

Avec la déclaration ci-dessus, vous ajoutez également $VoucherIDList à nouveau la liste.

Comme Alin dit ci-dessus, vous ajoutez la variable à lui-même de façon exponentielle chaque fois que la boucle se exécute.

Je suppose que cela est la raison pour laquelle vous avez trouvé les problèmes d'erreur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top