Die Geschichte der Frage:
Unterabfragen wurden ursprünglich in SQL eingeführt, um die Ausdrucksmöglichkeiten der Sprache zu erweitern und komplexe Geschäftsprobleme zu lösen, die sich nicht mit einfachen SELECT-Operatoren abbilden lassen. Mit der Zunahme von Datenvolumen und der Komplexität relationaler Modelle wurde jedoch klar, dass geschachtelte Unterabfragen nicht immer effizient arbeiten: Vieles hängt von der Implementierung des Optimierers der spezifischen Datenbank-Management-System (DBMS) ab.
Das Problem:
Die Hauptherausforderung besteht darin, einen Kompromiss zwischen Lesbarkeit, logischer Richtigkeit und Leistung zu finden. Nicht immer wird eine geschachtelte Unterabfrage zu JOIN-Operationen optimiert, oft verwandelt sie sich in kostspielige Schleifen (Nested Loops).
Die Lösung:
Beispielcode:
-- Geschachtelte Unterabfrage in SELECT (vorsichtig!) SELECT name, (SELECT COUNT(*) FROM orders WHERE orders.client_id = clients.id) AS order_count FROM clients; -- Entsprechendes über JOIN (gewöhnlich schneller): SELECT clients.name, COUNT(orders.id) AS order_count FROM clients LEFT JOIN orders ON orders.client_id = clients.id GROUP BY clients.name;
Wichtige Merkmale:
Läuft eine geschachtelte Unterabfrage in SELECT schneller als das entsprechende LEFT JOIN?
In der Regel — nein. Eine korrelierte Unterabfrage in SELECT wird für jede Zeile der äußeren Abfrage ausgeführt, während JOIN einmal mit Indizes für die gesamte Tabelle erstellt wird.
Kann man eine Unterabfrage in FROM anstelle von CTE (WITH) verwenden, und gibt es einen Unterschied?
Ja, eine Unterabfrage in FROM:**
SELECT t1.id, sub.agg FROM table1 t1 JOIN (SELECT id, MAX(val) AS agg FROM table2 GROUP BY id) sub ON t1.id = sub.id;
Aber CTE hat manchmal eine bessere Lesbarkeit und kann zu einer anderen Optimierung in den Ausführungsplänen führen.
Werden alle geschachtelten Unterabfragen in ähnliche JOINs optimiert?
Nein. Nicht alle DBMS können das gleich gut, manchmal führt eine geschachtelte Unterabfrage zu einem Scan jeder Zeile, insbesondere wenn eine Korrelation zwischen der äußeren und der inneren Abfrage besteht.
Ein Vertriebsleiter hat einen Bericht über Kunden erstellt, der in einer inneren SELECT-Anweisung die Anzahl der Bestellungen zählt. Die Ausführungszeiten belaufen sich auf Minuten, die Serverlast wuchs exponentiell.
Vorteile:
Die Abfrage wurde mit LEFT JOIN und Gruppierung umgeschrieben.
Vorteile: