Optimierung von SQL-Abfragen

Was ist ein Ausführungsplan in SQL?

Execution Plan, Query-Plan

Der Ausführungsplan (Execution Plan) ist die Schrittfolge, mit der eine Datenbank eine SQL-Abfrage tatsächlich abarbeitet: welche Tabellen sie in welcher Reihenfolge liest, ob sie dafür einen Index nutzt und wie sie Tabellen verbindet. Du beschreibst in SQL nur das gewünschte Ergebnis, den Weg dorthin wählt der Optimizer anhand von Statistiken.

Zwei Abfragen mit demselben Ergebnis können sich in der Laufzeit um Größenordnungen unterscheiden, und der Plan zeigt dir, an welcher Stelle das passiert.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Erzeugt von
Query-Optimizer der Datenbank
Abrufbar mit
EXPLAIN, im SQL Server über SHOWPLAN, in Oracle über DBMS_XPLAN
Beruht auf
Statistiken über Zeilenzahl und Werteverteilung
Warnsignal
Geschätzte und echte Zeilenzahl weichen stark ab

Wie der Optimizer zu einem Plan kommt

SQL ist deklarativ: Du schreibst, welche Zeilen du haben willst, nicht wie die Datenbank sie findet. Für eine Abfrage mit drei verbundenen Tabellen gibt es Dutzende mögliche Wege, etwa unterschiedliche Join-Reihenfolgen, Indexzugriffe oder vollständige Durchläufe. Der Optimizer schätzt für jede sinnvolle Variante die Kosten und nimmt die günstigste.

Grundlage dieser Schätzung sind Statistiken über die Daten: wie viele Zeilen eine Tabelle hat, wie viele verschiedene Werte eine Spalte enthält und wie sie verteilt sind. Fragst du zum Beispiel alle Bestellungen eines einzelnen Kunden ab, erwartet der Optimizer wenige Treffer und greift über den Index zu. Fragst du alle Bestellungen des letzten Jahres ab, liest er die Tabelle womöglich komplett, weil das bei vielen Treffern schneller ist.

Viele Datenbanken heben einmal berechnete Pläne auf. SQL Server und Oracle legen sie in einem Plan-Cache ab, PostgreSQL nutzt für Prepared Statements nach einigen Ausführungen unter Umständen einen generischen Plan. Das spart Rechenzeit, kann aber dazu führen, dass ein Plan, der für einen bestimmten Parameterwert gut war, bei einem anderen Wert schlecht passt.

So liest du den Plan

In PostgreSQL und MySQL stellst du EXPLAIN vor die Abfrage und bekommst den Plan als Baum. Gelesen wird er von innen nach außen: Die am weitesten eingerückten Knoten laufen zuerst und reichen ihre Zeilen nach oben weiter. Jeder Knoten trägt Startkosten, Gesamtkosten, erwartete Zeilenzahl und Zeilenbreite. Die Kosten sind eine dimensionslose Rechengröße, keine Millisekunden.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM bestellungen WHERE kunde_id = 4711;

Mit ANALYZE wird die Abfrage tatsächlich ausgeführt, und jeder Knoten bekommt zusätzlich die gemessene Zeit und die echte Zeilenzahl. Vergleiche in jedem Knoten Schätzung und Wirklichkeit. Weichen sie um Größenordnungen voneinander ab, hat der Optimizer auf falscher Grundlage entschieden, und alle Entscheidungen weiter oben im Baum sind ebenfalls fragwürdig.

BUFFERS zeigt, wie viele Blöcke aus dem Cache und wie viele von der Platte kamen, ab PostgreSQL 18 ist diese Angabe bei EXPLAIN ANALYZE automatisch dabei. Eine Abfrage, die beim zweiten Aufruf schnell ist, war oft nicht optimiert, sondern nur warmgelaufen.

Weil EXPLAIN ANALYZE die Anweisung wirklich ausführt, gehört ein UPDATE oder DELETE dabei in eine Transaktion, die du anschließend mit ROLLBACK zurückrollst. Sonst analysierst du deine Daten nicht, sondern änderst sie.

Was die häufigsten Knoten bedeuten

Die Namen stammen aus PostgreSQL, in anderen Datenbanken heißen die Operatoren ähnlich (im SQL Server etwa Table Scan, Index Seek und Hash Match). Kein Knoten ist für sich gut oder schlecht, entscheidend ist, ob er zur Zeilenzahl passt.

KnotenWas passiertPasst, wenn
Seq ScanLiest die ganze TabelleTabelle klein oder viele Treffer
Index ScanSpringt über den Index in die TabelleWenige Treffer
Index Only ScanLiest nur den Index, die Tabelle bleibt unberührtAlle Spalten stehen im Index
Bitmap Heap ScanSammelt Treffer im Index, liest dann blockweiseMittlere Treffermenge
Nested LoopDurchsucht für jede äußere Zeile die innere SeiteWenige äußere Zeilen
Hash JoinBaut eine Hashtabelle im SpeicherGroße Mengen ohne Sortierung
Merge JoinVerbindet zwei sortierte EingabenBeide Seiten liegen sortiert vor

Gefährlich wird ein Nested Loop, wenn der Optimizer zehn äußere Zeilen erwartet und es in Wahrheit hunderttausend sind. Achte außerdem auf Sort- und Hash-Knoten, die auf externen Speicher ausweichen: Reicht der Arbeitsspeicher nicht, schreibt die Datenbank Zwischenergebnisse auf die Platte, und das kostet mehr Zeit als jeder Indexzugriff.

Den Plan in anderen Datenbanken anzeigen

Das Prinzip ist überall gleich, nur die Befehle unterscheiden sich. Fast alle Systeme kennen einen geschätzten Plan, der nichts ausführt, und einen tatsächlichen Plan mit Messwerten.

DatenbankGeschätzter PlanMit Messwerten
PostgreSQLEXPLAINEXPLAIN ANALYZE
MySQLEXPLAIN, EXPLAIN FORMAT=TREEEXPLAIN ANALYZE (ab 8.0.18)
SQL ServerSET SHOWPLAN_XML ON, in SSMS Strg+LSET STATISTICS XML ON, in SSMS Strg+M
OracleEXPLAIN PLAN FOR, dann DBMS_XPLAN.DISPLAYDBMS_XPLAN.DISPLAY_CURSOR nach der Ausführung

Im SQL Server Management Studio erscheint der Plan grafisch, gelesen wird er dort von rechts nach links. Ein Ausrufezeichen am Operator weist auf eine Warnung hin, etwa eine fehlende Statistik oder eine implizite Typumwandlung, die einen Indexzugriff verhindert.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Nicht verwechseln

Ausführungsplan und was oft damit gleichgesetzt wird

Ausführungsplan gegen Ausführungsplan im Bauwesen

Auf der Baustelle meint Ausführungsplan etwas ganz anderes: die detaillierten Werkpläne aus der Ausführungsplanung, nach HOAI die Leistungsphase 5. Mit Datenbanken hat das nichts zu tun, die Seite hier behandelt nur den Plan einer SQL-Abfrage.

Ausführungsplan gegen Index

Der Index ist eine Datenstruktur, der Ausführungsplan die Entscheidung, ob sie benutzt wird. Ein vorhandener Index bringt nichts, wenn der Optimizer ihn für teurer hält als den vollständigen Tabellendurchlauf oder die Bedingung so formuliert ist, dass er nicht greifen kann.

Ausführungsplan gegen Query-Optimizer

Der Optimizer ist der Teil der Datenbank, der mögliche Pläne erzeugt, ihre Kosten schätzt und einen auswählt. Der Ausführungsplan ist das Ergebnis dieser Arbeit, den Optimizer selbst siehst du nie, nur seine Entscheidung.

Ausführungsplan gegen Slow-Query-Log

Das Protokoll langsamer Abfragen zeigt, welche Anweisung Zeit kostet und wie oft sie läuft. Warum sie langsam ist, erfährst du erst über ihren Ausführungsplan, beide Werkzeuge ergänzen sich also.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
In der Praxis

Fast immer sind es alte Statistiken oder ein Index, der nicht greift

Die Datenbank rät nicht, sie rechnet mit Statistiken über die Verteilung der Werte. Aktualisiert nach einem großen Import niemand diese Statistiken, hält der Optimizer eine Tabelle für klein, die inzwischen groß ist, und wählt ein Verfahren, das dafür nicht taugt. Liegen geschätzte und tatsächliche Zeilenzahl im Plan weit auseinander, ist das die erste Spur.

Der zweite Dauerbrenner: Der Index liegt auf der Spalte, aber die Bedingung steckt die Spalte in eine Funktion, etwa beim Vergleich von Datumsteilen oder beim Kleinschreiben für einen Textvergleich. Dann muss die Datenbank jede Zeile anfassen, obwohl der Index existiert, und im Plan steht statt eines Indexzugriffs ein vollständiger Durchlauf.

Und der Plan aus der Testumgebung sagt wenig, wenn dort nur ein Bruchteil der Daten liegt. Bei kleinen Tabellen ist der vollständige Durchlauf oft die schnellste Wahl, und genau derselbe Plan fällt im Produktivbetrieb auseinander. Deshalb lohnt der Blick auf den tatsächlich ausgeführten Plan mit echten Zeiten statt auf die reine Schätzung.

Ausführungsplan lernen

Wie du vom Plan zur konkreten Maßnahme kommst, statt auf Verdacht Indizes anzulegen, üben die PostgreSQL-Trainings für Entwicklung und Betrieb an eigenen Abfragen.

Häufige Fragen

Ist ein Seq Scan immer schlecht?
Nein. Bei kleinen Tabellen und bei Abfragen, die einen großen Teil der Zeilen liefern, ist das sequentielle Lesen der günstigste Weg. Kritisch wird es erst, wenn eine große Tabelle vollständig gelesen wird, obwohl nur eine Handvoll Zeilen gebraucht wird.
Warum ändert sich der Plan plötzlich?
Weil sich Datenmenge oder Werteverteilung geändert haben und der Optimizer daraufhin anders rechnet. Auch neue Indizes, geänderte Speicherparameter, aktualisierte Statistiken und ein Versionswechsel der Datenbank können den Plan kippen.
Kann ich der Datenbank einen bestimmten Plan vorschreiben?
Teilweise. Oracle und SQL Server kennen Hints, mit denen du etwa einen Index oder ein Join-Verfahren erzwingst, und der SQL Server kann über den Query Store einen bewährten Plan festhalten. PostgreSQL bringt keine Hints mit, dort steuerst du über Statistiken, Indizes und Parameter oder über die Erweiterung pg_hint_plan.
Was ist Parameter Sniffing?
So heißt im SQL Server der Effekt, dass ein Plan für den Parameterwert der ersten Ausführung optimiert und dann aus dem Cache wiederverwendet wird. Ist dieser erste Wert untypisch, laufen alle späteren Aufrufe mit einem unpassenden Plan, obwohl sich an der Abfrage nichts geändert hat.

Passt thematisch dazu

Wie du einen echten Plan Knoten für Knoten durchgehst, zeigt die ausführliche Anleitung zu Operatoren und Zeilenzahlen im Ausführungsplan.

Zeigt der Plan trotz passendem Index einen vollständigen Durchlauf, findest du hier die häufigsten Ursachen für einen ignorierten Index.

Persönlich für dich da

Deine Ansprechpartner

Du willst das Thema nicht nur nachschlagen, sondern anwenden können? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Ordnet mit dir ein, welcher Kurs zu deinem Vorwissen passt.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant Inhouse-Trainings, die an euren eigenen Daten und Abläufen ansetzen.

Ausführungsplan im Kurs statt im Lexikon

Nachschlagen bringt dich bis zum Verstehen. Anwenden lernst du an echten Aufgaben.