Eine Seite kann langsam sein, ohne eine einzige langsame Abfrage. Zwanzig Produkte, und für jedes eine Abfrage nach Kategorie, Preis und Bild: einundsechzig Abfragen, wo zwei genügten. Jede braucht zwei Millisekunden, und die Seite braucht anderthalb Sekunden.
Zählen Sie sie zuerst
// at the end of the page
echo count($pdo->query('SHOW SESSION STATUS LIKE "Questions"')->fetchAll());
Oder lesen Sie die Zahl aus der Debug-Leiste des Frameworks, oder aus dem Slow Log mit long_query_time auf 0 für eine einzige Anfrage. Die Zahl zählt mehr als jede einzelne Zeitmessung: unter 20 ist normal, über 100 ist der Fehler.
Wie es im Code aussieht
// 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);
}
Die Abhilfe ist ein Join oder eine Abfrage für alle IDs
$ids = array_column($products, 'category_id');
$cats = query('SELECT * FROM categories WHERE id IN (' . placeholders($ids) . ')', $ids);
// then match them up in PHP
Zwei Abfragen statt einundzwanzig, und es wird nicht schlimmer, wenn die Seite hundert Produkte zeigt - und genau das ist die Eigenschaft, auf die es ankommt.
In einem ORM
Dafür gibt es Eager Loading. Die faule Vorgabe ist bequem und erzeugt genau dieses Muster, und die Abhilfe ist meist ein einziges Wort.
$products = Product::with('category', 'images')->limit(20)->get();