Gegeben ist eine SQL-Query die mittels UNION zwei Tabellen vermischt und die 50 aktuellsten Datensätze nach Timestamp ausgibt. War mal schnell, mit ein paar mehr Datensätzen nicht mehr. Die Abfrage läuft ca. 5 Sekunden – zu lange, denn es geht auch schneller.
Derartige Queries lassen sich wie folgt beschleunigen:
- UNION ALL anstelle von UNION, das Aussortieren der ggf. doppelten Datensätzen über ein WHERE geht schneller, als das per default genutzte UNION DISTINCT … nicht wundern, ist so.
Damit sinkt die Laufzeit der Query von ca. 5 auf ca. 1,5 Sekunden, aber da geht noch mehr (der eigentlich logische Teil *hust*):
- wenn möglich sollte man die abzufragenden Datenmengen Inner-Queries entsprechend klein halten, wenn man z.B. eh nur 50 Datensätze aus 2 Tabellen kombinieren will, dann ist es sinnvoll auch nur diese in die Gesamtmenge einzubringen.
Laufzeit der Query nun wieder im Millisekundenbereich. Fertig ;)
Das eine geschickt formulierte where Klausel schneller geht als ein
union distinct ist eigentlich ziemlich leicht zu begreifen, wenn man sich den
Unterschied zwischen where und having ansieht:
* Where selektiert Datensätze aus der Datenbank und erzeugt die
Ergebnismenge
* Having filtert die Ergebnismenge und verkleinert damit die
Ausgabemenge
* Union nimmt beide Ausgabemengen und union distinct würde
also die Vereinigung beider Ausgabemengen nochmal filtern, wobei distinct ja
eine Sortierung der Ausgabemenge vorraussetzt, um die dopplungen zu erkennen.
Bei weitem die schnellste logische Methode um Datenmengen aus verschiedenen
Tabellen zu kombinieren ist ein inner join mit vernünftigen on und
where Selektoren.
Etwas schwieriger und langwieriger ist die Auswahl von Datensätzen deren
Bedingung eben nicht erfüllt ist:
Also alle Zeilen aus x, die keine Entsprechung in y haben.
Aber immer gilt die Regel, dass join und where vor der Erzeugung der
Ergebnismenge, schneller sind als union. Beim join muss man nur Aufpassen, dass
man nicht zu viele Datensätze erzeugt, da ohne Bedingung count(x) * count(y)
Datensätze geliefert werden. Mit der richtigen on Bedingung (zum
Beispiel mit dem Vergleich eines unique keys) bleiben sehr schnell nur noch
wenige Datensätze übrig.