SQL-Reihenfolge der Operationen – In welcher Reihenfolge führt MySQL Abfragen aus?
Klicken Sie zum Start, kostenlos.
Die Kenntnis der Bits und Bytes der Reihenfolge der Operationen einer SQL-Abfrage kann sehr wertvoll sein, da sie das Schreiben neuer Abfragen erleichtern kann, aber auch sehr nützlich ist, wenn man versucht, eine SQL-Abfrage zu optimieren.
In der Kurzfassung ist dies die logische Reihenfolge der Operationen, auch bekannt als Ausführungsreihenfolge, für eine SQL-Abfrage:
- VON, einschließlich JOINs
- WHERE
- GROUP BY
- HAVING
- WINDOW Funktionen
- SELECT
- DISTINCT
- UNION
- ORDER BY
- LIMIT und OFFSET
Aber die Realität ist weder so einfach noch einfach. Wie bereits erwähnt, definiert der SQL-Standard die Reihenfolge der Ausführung der verschiedenen SQL-Abfrageklauseln. Moderne Datenbanken stellen diese Standardreihenfolge bereits in Frage, indem sie einige Optimierungstricks anwenden, die die tatsächliche Ausführungsreihenfolge ändern können, obwohl sie am Ende das gleiche Ergebnis zurückgeben müssen, als ob sie die Abfrage in der Standardausführungsreihenfolge ausführen würden.
Warum sollten sie das tun? Nun, es kann dumm sein, wenn die Datenbank zuerst alle in der FROM-Klausel genannten Daten (einschließlich der JOINs) abruft, bevor sie die WHERE-Klausel und ihre Indizes untersucht. Diese Tabellen können viele Daten enthalten, so dass man sich vorstellen kann, was passieren würde, wenn sich der Optimierer der Datenbank an die traditionelle Reihenfolge der Operationen einer SQL-Abfrage halten würde.
Schauen wir uns die einzelnen Teile der SQL-Abfrage entsprechend ihrer Ausführungsreihenfolge an.
FROM und JOINs
Die in der FROM-Klausel angegebenen Tabellen (einschließlich JOINs) werden zuerst ausgewertet, um den gesamten für die Abfrage relevanten Arbeitssatz zu ermitteln. Die Datenbank führt die Daten aus allen Tabellen gemäß den JOINs ON-Klauseln zusammen, während sie auch Daten aus den Unterabfragen abruft, und kann sogar einige temporäre Tabellen erstellen, um die von den Unterabfragen in dieser Klausel zurückgegebenen Daten zu speichern.
In vielen Fällen wird der Optimierer der Datenbank jedoch zuerst den WHERE-Teil auswerten, um zu sehen, welcher Teil des Arbeitsdatensatzes weggelassen werden kann (vorzugsweise unter Verwendung von Indizes), so dass der Datensatz nicht zu sehr aufgebläht wird, wenn es nicht wirklich nötig ist.
WHERE-Klausel
Die WHERE-Klausel wird als zweite nach der FROM-Klausel ausgewertet.
Diese Bedingungen können Verweise auf die Daten und Tabellen aus der FROM-Klausel enthalten, aber keine Verweise auf Aliase, die in der SELECT-Klausel definiert sind, da diese Daten und Aliase in diesem Kontext noch nicht „existieren“, da diese Klausel noch nicht von der Datenbank ausgewertet wurde.
Eine häufige Fallgrube für die WHERE-Klausel ist auch der Versuch, aggregierte Werte in der WHERE-Klausel herauszufiltern, z. B. mit dieser Klausel: „WHERE sum(available_stock) > 0“. Diese Anweisung führt zum Scheitern der Abfrage, da die Aggregate erst später im Prozess ausgewertet werden (siehe Abschnitt GROUP BY weiter unten). Um Filterbedingungen auf aggregierte Daten anzuwenden, sollten Sie die HAVING-Klausel und nicht die WHERE-Klausel verwenden.
GROUP BY-Klausel
Nachdem wir den Datensatz mit Hilfe der WHERE-Klausel gefiltert haben, können wir die Daten nach einer oder mehreren Spalten aggregieren, die in der GROUP BY-Klausel erscheinen. Das Gruppieren der Daten bedeutet, dass sie in verschiedene Abschnitte oder Bereiche aufgeteilt werden, wobei jeder Bereich einen Schlüssel und eine Liste von Zeilen enthält, die mit diesem Schlüssel übereinstimmen. Ohne GROUP BY-Klausel ist es so, als würde man alle Zeilen in einen einzigen großen Bereich packen.
Nach dem Aggregieren der Daten können Sie nun Aggregationsfunktionen verwenden, um einen Wert pro Gruppe für jeden der Bereiche zurückzugeben. Solche Aggregationsfunktionen sind COUNT, MIN, MAX, SUM und andere.
HAVING-Klausel
Nachdem wir die Daten mit der GROUP BY-Klausel gruppiert haben, können wir die HAVING-Klausel verwenden, um einige Bereiche herauszufiltern. Die Bedingungen in der HAVING-Klausel können sich auf die Aggregationsfunktionen beziehen, so dass das Beispiel, das in der WHERE-Klausel oben nicht funktioniert hat, in der HAVING-Klausel problemlos funktioniert: „HAVING sum(available_stock) > 0“.
Da wir die Daten bereits gruppiert haben, können wir an dieser Stelle nicht mehr auf die ursprünglichen Zeilen zugreifen, so dass wir nur Bedingungen anwenden können, um ganze Bereiche zu filtern, und nicht einzelne Zeilen in einem Bereich.
Auch auf die in der SELECT-Klausel definierten Aliase kann, wie bereits erwähnt, in diesem Abschnitt nicht zugegriffen werden, da sie von der Datenbank noch nicht ausgewertet wurden (dies gilt für die meisten Datenbanken).
Fensterfunktionen
Wenn Sie Fensterfunktionen verwenden, werden sie an dieser Stelle ausgeführt. Genau wie der Gruppierungsmechanismus führen auch die Fensterfunktionen eine Berechnung auf einer Reihe von Zeilen aus. Der Hauptunterschied besteht darin, dass bei der Verwendung von Window-Funktionen jede Zeile ihre eigene Identität behält und nicht in einem Eimer mit anderen ähnlichen Zeilen gruppiert wird.
Window-Funktionen können nur in der SELECT- oder ORDER BY-Klausel verwendet werden. Sie können Aggregationsfunktionen innerhalb der Fensterfunktionen verwenden, zum Beispiel:
SUM(COUNT(*)) OVER ()
SELECT-Klausel
Nachdem wir nun die Zeilen aus dem Datensatz entfernt und die Daten gruppiert haben, können wir die Daten auswählen, die aus der Abfrage auf die Client-Seite geholt werden sollen. Sie können Spaltennamen, Aggregationen und Unterabfragen in der SELECT-Klausel verwenden. Beachten Sie, dass, wenn Sie einen Verweis auf eine Aggregationsfunktion wie COUNT(*) in der SELECT-Klausel verwenden, dies lediglich ein Verweis auf eine Aggregation ist, die bereits stattgefunden hat, als die Gruppierung stattfand, so dass die Aggregation selbst nicht in der SELECT-Klausel stattfindet, sondern dies nur ein Verweis auf ihre Ergebnismenge ist.
Schlüsselwort DISTINCT
Die Syntax des Schlüsselworts DISTINCT ist etwas verwirrend, da das Schlüsselwort in der SELECT-Klausel vor den Spaltennamen steht. Die eigentliche DISTINCT-Operation findet jedoch nach der SELECT-Klausel statt. Bei Verwendung des Schlüsselworts DISTINCT verwirft die Datenbank Zeilen mit doppelten Werten aus den verbleibenden Zeilen, die nach dem Filtern und Aggregieren übrig geblieben sind.
Schlüsselwort UNION
Das Schlüsselwort UNION kombiniert die Ergebnismengen von zwei Abfragen zu einer Ergebnismenge. Bei den meisten Datenbanken kann man zwischen UNION DISTINCT (verwirft doppelte Zeilen in der kombinierten Ergebnismenge) und UNION ALL (kombiniert die Ergebnismengen einfach, ohne eine Duplikatsprüfung durchzuführen) wählen.
Sie können auf die Ergebnismenge von UNION eine Sortierung (ORDER BY) und eine Begrenzung (LIMIT) anwenden, genauso wie bei einer regulären Abfrage.
ORDER BY-Klausel
Die Sortierung erfolgt, sobald die Datenbank die gesamte Ergebnismenge zur Verfügung hat (nach dem Filtern, Gruppieren und Entfernen von Duplikaten). Danach kann die Datenbank die Ergebnismenge anhand von Spalten, ausgewählten Aliasen oder Aggregationsfunktionen sortieren, auch wenn diese nicht Teil der ausgewählten Daten sind. Die einzige Ausnahme ist die Verwendung des Schlüsselworts DISTINCT, das die Sortierung nach einer nicht ausgewählten Spalte verhindert, da in diesem Fall die Reihenfolge der Ergebnismenge undefiniert ist.
Sie können wählen, ob Sie die Daten in absteigender (DESC) oder aufsteigender (ASC) Reihenfolge sortieren. Die Reihenfolge kann für jeden der Ordnungsbestandteile eindeutig sein, so dass Folgendes gültig ist: ORDER BY firstname ASC, age DESC
LIMIT und OFFSET
In den meisten Anwendungsfällen (mit Ausnahme einiger weniger wie z.B. bei der Berichterstellung) möchten wir alle Zeilen außer den ersten X Zeilen des Abfrageergebnisses verwerfen. Die LIMIT-Klausel, die nach der Sortierung ausgeführt wird, ermöglicht genau das. Außerdem können Sie mit einer Kombination aus den Schlüsselwörtern LIMIT und OFFSET festlegen, ab welcher Zeile die Daten abgerufen werden sollen und wie viele davon ausgeschlossen werden sollen. Das folgende Beispiel holt 50 Zeilen ab Zeile #100: LIMIT 50 OFFSET 100
Klicken Sie, um zu beginnen, kostenlos.