Bir sayfa, tek bir yavaş sorgu olmadan da yavaş olabilir. Yirmi ürün ve her biri için kategorisini, fiyatını ve görselini soran birer sorgu: ikisinin yeteceği yerde altmış bir sorgu. Her biri iki milisaniye alır, sayfa ise bir buçuk saniye.

Önce onları sayın

// at the end of the page
echo count($pdo->query('SHOW SESSION STATUS LIKE "Questions"')->fetchAll());

Ya da sayıyı çerçevenizin hata ayıklama çubuğundan okuyun, ya da tek bir istek için long_query_time'ı 0 yapıp yavaş kayıttan. Sayı, herhangi bir tekil süreden daha önemlidir: 20'nin altı olağandır, 100'ün üstü hatanın kendisidir.

Kodda neye benzediği

// N+1: one query, then one more per row
$products = query('SELECT * FROM products LIMIT 20');
foreach ($products as $p) {
    $p->category = query('SELECT * FROM categories WHERE id = ?', $p->category_id);
}

Çaresi bir birleştirme ya da bütün kimlikler için tek sorgu

$ids = array_column($products, 'category_id');
$cats = query('SELECT * FROM categories WHERE id IN (' . placeholders($ids) . ')', $ids);
// then match them up in PHP

Yirmi bir yerine iki sorgu ve sayfa yüz ürün gösterdiğinde de kötüleşmiyor - asıl önemli olan özellik de bu.

Bir ORM içinde

İştahlı yükleme tam bunun içindir. Tembel varsayılan kullanışlıdır ve tam da bu biçimi üretir; çaresi de çoğu kez tek bir kelimedir.

$products = Product::with('category', 'images')->limit(20)->get();
Böyle bir sayfayı önbelleğe almak, önbellek soğuyana kadar sorunu gizler; her dağıtımdan sonraki ilk ziyaretçi de 400 sorgunun tamamını alır. Önce sayıyı düzeltin, sonra önbelleğe alın.
Sayfa büyürken sorgu sayısını izleyin. 1 satır için 3, 100 satır için 300 sorgu çalıştıran bir sayfa bu biçimdedir, süreler bugün ne derse desin.