Bir veritabanında satırlar üzerinde yineleme ve bunları kaldırarak

4 Cevap php

Ben sadece kontrol etmek istiyorum, bu bir veritabanında satırlar üzerinde yineleme ve işlendiğinde onları silmek iyi bir yoldur? Ben ilk vardı

  • Tüm tut
  • Süreç bütün
  • Tümünü sil

Ancak yeni satırlar ilave olsaydı "Süreç tüm" adımı çalışırken ki (dışarıdan) sorunları bırakın düşündüm.

// the limited for loop is to prevent an infinite loop
// assume the limit to be much higher than the expected
// number of rows to process
for ($i = 0; $i < $limit; $i++) 
{

    // get next mail in queue
    $st = $db->prepare('
        SELECT id, to, subject, message, attachment
        FROM shop_mailqueue
        LIMIT 0,1
    ');
    $st->execute();
    $mail = $st->fetch(PDO::FETCH_ASSOC);

    // if no more mails in queue, stop
    if ($mail === false) {
        break;
    }

    // send queued mail
    $mailer = new PHPMailer();
    $mailer->AddAddress($mail['to']);
    $mailer->SetFrom('info@xxx.nl', 'xxx.nl');
    $mailer->Subject = $mail['subject'];
    $mailer->Body = $mail['message'];
    $mailer->AddAttachment($mail['attachment']);
    $mailer->Send();

    // remove mail from queue
    $st = $db->prepare('
        DELETE FROM shop_mailqueue WHERE id = :id
    ');
    $st->bindValue('id', $mail['id']);
    $st->execute();

}

4 Cevap

Ben senin kapmak tüm süreç hepsi, hepsi yaklaşım silmek basit bir değişiklik ile iyi olduğunu düşünüyorum:

  • Instead of doing a simple delete from table, do a delete from table where key in (<all keys retrieved>).

Öncelikle her şeyi kapmak için kolayca retrieved>

Bu şimdi yapmayı planladığınız gibi çok sayıda sorgu yaparak daha (çok) daha iyi performans gösterecektir.

Birincisi ve en önemlisi, size daha iyi her satır için oluyor bazı ciddi karmaşık işleyişi hakkında konuşuyor ", bir veritabanı satırları fazla yineleme" demek, her zaman. Aksi takdirde, ve setleri düşünmek gerektiğini olabilir!

Eğer posta kuyruğunda her şeyi alarak ve tüm e-postaları gönderdikten sonra tabloyu damping konum gibi görünüyor. Şimdi, hiçbir order by beri sizin limit 0,1, burada biraz Kaygılı olduğunu dikkat etmelisiniz. Hiçbir veritabanı güvenilir sırayla şeyleri saklar (ve iyi bir sebeple - sürekli onları optimize etmek şeyleri taşımak için vardır). Yani, daha iyi kod olacaktır:

// get next mail in queue
$st = $db->prepare('
    SELECT id, to, subject, message, attachment
    FROM shop_mailqueue
    ORDER BY id ASC
    LIMIT 0, ' . $limit);
        $st->execute();

$lastid = 0;

while ($mail = $st->fetch(PDO::FETCH_ASSOC))
{    
    // send queued mail
    $mailer = new PHPMailer();
    $mailer->AddAddress($mail['to']);
    $mailer->SetFrom('info@xxx.nl', 'xxx.nl');
    $mailer->Subject = $mail['subject'];
    $mailer->Body = $mail['message'];
    $mailer->AddAttachment($mail['attachment']);
    $mailer->Send();

    $lastid = $mail['id'];
}


// remove mail from queue
$st = $db->prepare('DELETE FROM shop_mailqueue WHERE id <= ' . $lastid);
$st->execute();

Bu şekilde, sadece geri her zaman bir satır çekerek daha much daha optimal veritabanına iki (sayısı 'em!) Sorguları yapıyoruz.

Bütün $limit anlaşma gereksiz ve gerçekten sıraya geri satırların tümünü çekin ve sonra sadece kuyruğunu dışarı dökümü istiyorsanız Şimdi, sizin delete deyimi değiştirin:

TRUNCATE TABLE shop_mailqueue

truncate işlem mantığı ile bağlı değildir ve sadece masa temiz mendil, hiçbir soru sordu, bakın. Bu nedenle, (ne olursa olsun tablo boyutu, milisaniye gibi) son derece hızlı. delete sadece hız bu tür yoktur. Sadece truncate nükleer seçenek olduğunu unutmayın - truncate, gitti gitti bir kere.

Sen sürecinde kilit tablo olabilir

http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html

Ne yapıyorsun gayet iyi bence. Sen olduğunu bütün getir, bunları işlemek ve sadece işlenmiş olanlar silin. Eğer kayıtları yaratmak isteyenlere engeller çünkü ben de, senin sürecinde kilit tablo olmaz.

Sahip tek sorun mevcut olanları gönderiyor iken oluşturulmuş olabilir bu e-postaları işlemek için ise, o zaman sadece her zaman çalıştırmak için tüm prosedür üstüne bir while döngü yaratabilir yeni kayıtları vardır.

Buna ek olarak, neden sadece tek bir sorguda max $ limit ürün almak için sorguyu değiştirebilirsiniz eğer, LIMIT 0,1 ($limit) kez elde LIMIT 0,$limit.