Ein kleine Lektion über Datenbank-Performance

Kategorie Webentwicklung
Inhalt
Was mag wohl schneller sein? Version 1:

SELECT element_id
FROM matches
JOIN objects ON object_id=element_id
WHERE parent_id IN($pids) AND inactive=0
ORDER BY create_date DESC

oder Version 2:

SELECT object_id
FROM objects
WHERE object_id IN
(
SELECT element_id
FROM matches
WHERE parent_id IN ($pids)
)
AND inactive=0
ORDER BY create_date DESC

Die Fragestellung sagt schon, beide waren nicht gleich schnell, obwohl sie dasselbe tun.
Version 1 braucht 400 Millisekunden, Version 2 braucht 100 Millisekunden.

Das Problem in ersterem Fall war ein Table Scan auf der objects-Tabelle, um festzustellen, wo inactive=0 ist. Wieso der PostgresQL-Optimizer auf die Idee kam anzunehmen, daß er die Tabelle komplett durchsuchen müsse, kann ich mir nicht so recht erklären, immerhin beschränkt der andere Teil der WHERE-Bedingung die Zahl der Ergebnisse auf 20000 von 800000.
Ach, und natürlich liegt auf inactive ein Index, aber der ist ziemlich oft eher nutzlos (gerade mal 10000 Einträge haben da einen Wert <> 0).

Nun optimiere ich also für den Optimizer... das wird sich bestimmt irgendwann rächen.

Diashow
Blog