SQL Server Query Store aktivieren und nutzen
Der Flugschreiber des SQL Servers – sinnvoll konfiguriert, bevor das Problem auftritt.
Query Store aktivieren und nutzen
Der Flugschreiber des SQL Servers: Plan-Regressionen erkennen, Ressourcenfresser finden, Upgrades absichern — wenn er rechtzeitig läuft.
Stell dir ein Flugzeug ohne Flugschreiber vor. Solange alles glattgeht, fehlt er niemandem. Aber im Moment eines Zwischenfalls — wenn die entscheidende Frage lautet, was in den letzten Minuten eigentlich passiert ist — steht die Crew mit leeren Händen da: keine Aufzeichnung, keine Beweise, nur Vermutungen. Genau so ergeht es DBAs, die nach einer plötzlichen Performance-Verschlechterung herausfinden wollen, welcher Ausführungsplan gekippt ist — und feststellen, dass der gute alte Plan längst aus dem Cache geflogen ist und es keine Aufzeichnung gibt. Das Wissen, das sie jetzt bräuchten, hätte man sammeln müssen, bevor das Problem auftrat.
Der Query Store ist dieser Flugschreiber. Er zeichnet kontinuierlich auf, welche Abfragen mit welchen Plänen und welcher Performance liefen — und überlebt dabei Neustarts, Failover und Cache-Leerungen, weil er die Daten in der Datenbank selbst speichert. Dieser Beitrag aus dem SQL-Server-Notarztwagen (die Triage-Übersicht liegt unter /sql-server-notarztwagen/) zeigt dir, wie du ihn aktivierst, was er aufzeichnet und wie du mit ihm Plan-Regressionen nicht nur findest, sondern in Minuten entschärfst. Als Beitrag der GRÜN-Stufe ist seine wichtigste Botschaft eine Vorsorge-Botschaft: Aktiviere ihn jetzt, solange alles ruhig ist — denn ein Flugschreiber, der erst nach dem Absturz eingeschaltet wird, ist nutzlos.
Was der Query Store ist — und was ihn besonders macht
Der Query Store ist ein in jede Datenbank eingebautes Aufzeichnungs- und Analyse-System für Abfrage-Performance, eingeführt mit SQL Server 2016. Er protokolliert laufend vier Dinge: die Abfrage-Texte, die der Server ausführt, alle Ausführungspläne je Abfrage (nicht nur den aktuellen — auch die historischen), die Laufzeit-Statistik je Plan (Dauer, CPU, Reads, Ausführungszahl, jeweils über Zeitintervalle aggregiert) und seit neueren Versionen sogar die Wartetypen je Abfrage. Damit beantwortet er die Frage, an der jede nachträgliche Performance-Analyse sonst scheitert: Wie lief diese Abfrage gestern, letzte Woche, vor dem Release — und mit welchem Plan?
Das Besondere ist die Persistenz. Der herkömmliche Plan-Cache ist flüchtig: Bei jedem Neustart, jedem Failover, jeder Speicher-Knappheit und bei jedem Statistik-Update fliegen Pläne hinaus, und mit ihnen die Information, wie es vorher war. Der Query Store dagegen schreibt seine Aufzeichnungen in die Datenbank — sie wandern bei einem Failover mit, überstehen jeden Neustart und sind nach einem Upgrade noch da. Das macht ihn zum einzigen Werkzeug, mit dem du ein „gestern war es noch schnell“ überhaupt belegen kannst, statt es nur zu behaupten. Er verwandelt Performance-Diagnose von Archäologie in Aktenrecherche.
Und der Query Store ist nicht nur ein Beobachter, sondern auch ein Eingriffswerkzeug. Sein mächtigstes Feature ist das Plan-Forcing: Wenn der Optimizer eine Abfrage plötzlich mit einem schlechteren Plan ausführt, kannst du ihn zwingen, zum bewährten alten Plan zurückzukehren — ohne eine Zeile Code zu ändern, ohne Wartungsfenster, in Sekunden. Damit wird aus dem Flugschreiber ein Reparatur-Werkzeug, das in genau dem Moment hilft, in dem es darauf ankommt. Der Zusammenhang zu Plan-Regressionen ist so eng, dass er einen eigenen Beitrag hat — den über Statistiken und Parameter Sniffing.
|
Warum die Persistenz alles ändert Der Plan-Cache ist flüchtig: Neustart, Failover, Statistik-Update — und die Historie ist weg. |
|---|
Der Workflow: vom Aktivieren zum Forcing
Die folgende Übersicht zeigt, was der Query Store aufzeichnet und wie der typische Reparatur-Ablauf von der Regression bis zum erzwungenen Plan aussieht — mit der wichtigsten Regel ganz unten:

Die Skripte: aktivieren, auswerten, forcen
Schritt 1 — Aktivieren mit sinnvollen Einstellungen
Die Aktivierung ist eine Zeile, die sinnvolle Konfiguration ein paar mehr. So setzt du den Query Store auf, dass er zuverlässig sammelt, ohne überzulaufen:
|
— Query Store aktivieren und konfigurieren ALTER DATABASE [MeineDB] SET QUERY_STORE = ON;
ALTER DATABASE [MeineDB] SET QUERY_STORE ( OPERATION_MODE = READ_WRITE, — sonst sammelt er nicht MAX_STORAGE_SIZE_MB = 2048, — grosszuegig dimensionieren QUERY_CAPTURE_MODE = AUTO, — triviale Einmal-Abfragen ignorieren INTERVAL_LENGTH_MINUTES = 60, — Aggregations-Intervall CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30) );
— Status und Fuellstand pruefen SELECT actual_state_desc, readonly_reason, current_storage_size_mb, max_storage_size_mb FROM sys.database_query_store_options; |
|---|
Achte besonders auf actual_state_desc: Steht dort READ_ONLY statt READ_WRITE, sammelt der Query Store nicht mehr — meist, weil der Speicher voll ist (readonly_reason verrät es). Ein voller, in READ_ONLY gekippter Query Store ist ein abgeschalteter Flugschreiber; deshalb gehört der Füllstand überwacht und die Größe großzügig gewählt.
Schritt 2 — Regressionen programmatisch finden
Die SSMS-Berichte sind der schnellste Weg, aber für Automatisierung und Überblick lohnt der direkte Zugriff auf die Systemsichten. Diese Abfrage findet Abfragen mit mehreren Plänen und großer Laufzeit-Spreizung — die klassischen Regressions-Kandidaten:
|
— Regressions-Kandidaten: mehrere Plaene, grosse Laufzeit-Spreizung SELECT TOP (15) q.query_id, OBJECT_NAME(q.object_id) AS Objekt, COUNT(DISTINCT p.plan_id) AS AnzahlPlaene, MIN(rs.avg_duration) / 1000.0 AS BesteAvgMs, MAX(rs.avg_duration) / 1000.0 AS SchlechtesteAvgMs, SUBSTRING(qt.query_sql_text, 1, 120) AS AbfrageAuszug FROM sys.query_store_query AS q JOIN sys.query_store_query_text AS qt ON qt.query_text_id = q.query_text_id JOIN sys.query_store_plan AS p ON p.query_id = q.query_id JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id GROUP BY q.query_id, q.object_id, qt.query_sql_text HAVING COUNT(DISTINCT p.plan_id) > 1 ORDER BY MAX(rs.avg_duration) – MIN(rs.avg_duration) DESC; |
|---|
Schritt 3 — Den guten Plan erzwingen (und wieder freigeben)
|
— Plan-Forcing: bewaehrten Plan erzwingen EXEC sp_query_store_force_plan @query_id = 4711, @plan_id = 42;
— Spaeter, nach behobener Ursache, wieder freigeben EXEC sp_query_store_unforce_plan @query_id = 4711, @plan_id = 42;
— Welche Plaene sind aktuell geforct? (Wiedervorlage-Liste!) SELECT p.query_id, p.plan_id, p.is_forced_plan, p.force_failure_count FROM sys.query_store_plan AS p WHERE p.is_forced_plan = 1; |
|---|
Die letzte Abfrage ist wichtiger, als sie aussieht: Sie ist deine Inventarliste der Pflaster. Jeder geforcte Plan ist eine bewusst gesetzte Krücke — und force_failure_count größer null verrät, wenn ein geforcter Plan gar nicht mehr angewendet werden kann (etwa weil ein Index gelöscht wurde). Solche Karteileichen gehören aufgeräumt.
Die drei großen Anwendungsfälle
1. Plan-Regression erkennen und sofort entschärfen
Der Paradefall: Eine zentrale Abfrage wird über Nacht zehnmal langsamer, weil der Optimizer nach einem Statistik-Update oder Neustart einen schlechteren Plan gewählt hat. Mit dem Query Store ist das in Minuten erledigt — Regressed-Queries-Bericht öffnen, den guten alten Plan im Vergleich identifizieren, forcen. Die Anwender merken die Entschärfung sofort, und du hast Zeit gewonnen, die eigentliche Ursache in Ruhe zu beheben. Das ist die schnellste seriöse Antwort auf eine Regression überhaupt — und der häufigste Grund, warum erfahrene DBAs den Query Store nie missen wollen. Die ganze Mechanik dahinter steht im Statistiken-und-Sniffing-Beitrag der GELB-Stufe.
2. Die wahren Ressourcenfresser finden
Die Frage „welche Abfrage kostet uns am meisten?“ beantwortet der Query Store zuverlässiger als jede Momentaufnahme. Der Bericht Top Resource Consuming Queries zeigt die größten Verbraucher nach CPU, Dauer, Reads oder Speicher — über einen wählbaren Zeitraum, nicht nur den aktuellen Augenblick. Das ist Gold für die gezielte Optimierung: Statt zu raten, welche Abfrage Aufmerksamkeit verdient, siehst du die Top-Liste mit echten Zahlen über Tage. Und weil die Daten persistent sind, erwischst du auch den nächtlichen Report, der tagsüber unsichtbar ist — ein blinder Fleck jeder Live-Diagnose.
3. Upgrades und Änderungen absichern
Der vielleicht unterschätzteste Anwendungsfall. Jedes Upgrade mit Wechsel des Kompatibilitätsgrads wechselt auch den Kardinalitätsschätzer — und der rechnet manche Abfragen anders, was zu Regressionen führen kann. Der professionelle Ablauf nutzt den Query Store als Sicherheitsnetz: vor dem Upgrade aktivieren und eine Baseline der bewährten Pläne sammeln, nach dem Upgrade den Regressed-Queries-Bericht abarbeiten und Ausreißer per Forcing auf den alten Plan nageln, bis sie einzeln geprüft sind. So wird aus dem Upgrade-Roulette ein kontrollierter Prozess — dieselbe Technik schützt übrigens auch bei Cumulative Updates und Migrationen, nachzulesen in den entsprechenden Beiträgen.
Was du auf keinen Fall tun solltest
|
Die drei häufigsten Anfängerfehler 1. Den Query Store als reaktives Werkzeug behandeln. Er ist Vorsorge: Sein ganzer Wert hängt daran, dass er vor dem Problem läuft. |
|---|
Query Store als Standard-Ausstattung
Die Empfehlung ist so einfach wie wichtig: Aktiviere den Query Store auf jeder Produktions-Datenbank — nicht erst bei Problemen, sondern als Standard-Ausstattung wie ein Backup-Job. Drei Punkte machen daraus eine verlässliche Routine: Erstens, die Aktivierung in den Standard für neue Datenbanken aufnehmen (seit SQL Server 2022 ohnehin Default, davor manuell). Zweitens, den Füllstand überwachen, damit der Flugschreiber nicht unbemerkt in READ_ONLY kippt — das gehört in den Health Check. Drittens, eine Wiedervorlage-Liste für geforcte Pläne führen, damit die Pflaster von heute nicht die vergessenen Altlasten von morgen werden. So wird der Query Store vom Notfall-Werkzeug zur stillen Versicherung, die im Hintergrund läuft und im Ernstfall da ist.
Vertiefung in der Buchreihe
Query Store, Plan-Mechanik und die Forcing-Strategie füllen in der Buchreihe „SQL Server in der Praxis“ ein eigenes Kapitel — alle Bände in der Übersicht auf der SQL-Pillar-Seite unter /sql-server/.
|
Empfohlener Band Band 1: Performance & Troubleshooting — das Heimatbuch dieses Beitrags: Query Store von der Aktivierung über alle Berichte und Systemsichten bis zur Forcing-Strategie, die Wartetypen-Erfassung, die Konfigurations-Feinheiten und das Zusammenspiel mit Kardinalitätsschätzer und Plan-Cache. |
|---|
Verwandte Beiträge im Notarztwagen
Der Query Store ist mit vielen Themen verwoben — diese Beiträge aus dem Cluster lohnen den Blick:
Drei Wege zum aktiven Flugschreiber
Selbst-Diagnose-Kit
Den Query Store einzurichten und zu beherrschen ist die klassische Selbstmach-Aufgabe mit großer Vorsorge-Wirkung — und genau dafür gibt es das Diagnose-Kit. Es bündelt die Skripte aus diesem Beitrag — Aktivierung mit sinnvollen Einstellungen, Status- und Füllstands-Check, Regressions-Suche über die Systemsichten, Forcing-Vorlagen und die Inventarliste geforcter Pläne — plus den Workflow zum Ausdrucken und eine Konfigurations-Checkliste für unterschiedliche Workload-Größen. Damit rüstest du deine Datenbanken in einer Stunde mit dem Flugschreiber aus, der dir im Ernstfall Tage spart.
Festpreis-Analyse
Du willst den Query Store nicht nur aktivieren, sondern gleich die Erkenntnisse ernten, die er bereits gesammelt hat — Regressionen, Ressourcenfresser, instabile Abfragen? Die Festpreis-Analyse liefert genau das: Ich werte den vorhandenen Query Store deiner Datenbanken aus, identifiziere die größten Optimierungs-Hebel und Regressions-Risiken, prüfe die Konfiguration und liefere einen Bericht mit priorisierten Maßnahmen — und richte den Query Store dort ein, wo er noch fehlt. Zum vereinbarten Festpreis, ohne Stundenzähler.
Akut-Hotline
Wenn gerade jetzt ein Plan gekippt ist und du den Query Store gemeinsam zur Reparatur nutzen willst: anrufen. Halte einen Zugang mit den nötigen Rechten bereit — ist der Query Store aktiv, ist der gute alte Plan meist in Minuten gefunden und geforct; falls nicht, richten wir ihn ein und sichern wenigstens die Zukunft ab.
|
Ein letzter Tipp Prüfe heute auf deiner wichtigsten Datenbank eine einzige Sache: Ist der Query Store aktiv und im READ_WRITE-Modus? Eine Abfrage, dreißig Sekunden. Wenn die Antwort nein lautet, aktiviere ihn jetzt — nicht beim nächsten Problem, sondern jetzt, solange alles ruhig ist. Es ist die billigste Versicherung im ganzen DBA-Alltag: Du zahlst ein bisschen Speicher und bekommst dafür beim nächsten gekippten Plan die Beweise und das Gegenmittel frei Haus. |
|---|
Häufige Fragen (FAQ)
Diese Sektion ist auf häufige Suchanfragen abgestimmt. Sie hilft dir, schnell den Punkt zu finden, der dir gerade akut weiterhilft — und sie ist gleichzeitig die Eingabe für das FAQPage-Schema auf der Seite.
Wie aktiviere ich den Query Store?
Pro Datenbank mit ALTER DATABASE [DB] SET QUERY_STORE = ON, anschließend die Sammeloptionen setzen (OPERATION_MODE = READ_WRITE und die Größen- und Aufbewahrungseinstellungen). In SSMS geht es auch grafisch über die Datenbankeigenschaften. Wichtig zu wissen: Der Query Store wird je Datenbank aktiviert, nicht je Instanz, und seit SQL Server 2022 ist er bei neuen Datenbanken standardmäßig an. Bei bestehenden, migrierten oder älteren Datenbanken musst du ihn aber selbst einschalten — und genau das sollte auf jeder Produktions-Datenbank passieren, solange alles ruhig läuft, denn als Flugschreiber muss er vor dem Problem laufen, nicht danach.
Was ist Plan-Forcing?
Plan-Forcing heißt: Du legst im Query Store fest, dass eine Abfrage einen bestimmten, bewährten Ausführungsplan verwenden muss — der Optimizer darf nicht mehr frei wählen. Es ist die schnellste seriöse Antwort auf eine Plan-Regression: Im Query-Store-Bericht den guten alten Plan markieren, „Force Plan“ klicken oder sp_query_store_force_plan ausführen, und die Abfrage läuft sofort wieder mit dem bewährten Plan — ohne Code-Änderung, ohne Wartungsfenster. Forcing ist allerdings ein Pflaster mit Ablaufdatum: Die eigentliche Ursache der Regression (veraltete Statistik, fehlender Index) gehört trotzdem behoben, und geforcte Pläne gehören auf eine Wiedervorlage-Liste.
Wie finde ich Performance-Regressionen?
Am bequemsten über den eingebauten SSMS-Bericht „Regressed Queries“ unter dem Query-Store-Knoten der Datenbank: Er zeigt Abfragen, deren Laufzeit oder Ressourcenverbrauch sich verschlechtert hat, samt ihrer Plan-Historie — und im Plan-Vergleich siehst du schwarz auf weiß, was gekippt ist (Scan statt Seek, Hash statt Loop). Programmatisch findest du dieselben Kandidaten über die Query-Store-Systemsichten, indem du Abfragen mit mehreren Plänen und großer Laufzeit-Spreizung suchst. Ohne Query Store bleibt nur der mühsame Vergleich über dm_exec_query_stats, der bei jedem Neustart bei null beginnt — einer der Hauptgründe, den Query Store überhaupt zu aktivieren.
Welche Reports liefert der Query Store?
SSMS bietet unter dem Query-Store-Knoten mehrere fertige Berichte: „Regressed Queries“ (was wurde langsamer?), „Top Resource Consuming Queries“ (die größten Ressourcenfresser nach CPU, Dauer, Reads oder Speicher), „Overall Resource Consumption“ (der Gesamtverbrauch über die Zeit), „Queries With High Variation“ (instabile Abfragen mit schwankender Performance — oft Sniffing-Verdächtige) und „Queries With Forced Plans“ (die Übersicht deiner geforcten Pläne). Diese Berichte sind der schnellste Einstieg, weil sie die Systemsichten grafisch aufbereiten und Plan-Vergleich sowie Forcing per Klick erlauben. Für Automatisierung greifst du auf die zugrunde liegenden sys.query_store_-Sichten zu.
Wie nutze ich sys.query_store_query_text?
Diese Systemsicht enthält die erfassten Abfrage-Texte und ist der Einstieg, wenn du den Query Store programmatisch statt über die SSMS-Berichte auswertest. Über query_text_id verknüpfst du sie mit sys.query_store_query (die Abfrage-Metadaten), von dort über query_id mit sys.query_store_plan (die Pläne) und schließlich mit sys.query_store_runtime_stats (die Laufzeit-Statistik je Plan und Zeitintervall). Diese vier Sichten zusammen erlauben jede Auswertung, die auch die Berichte liefern — etwa Abfragen mit mehreren Plänen und großer Laufzeit-Spreizung als Regressions-Kandidaten zu finden. Ein Beispiel-Join steht im Skript-Abschnitt dieses Beitrags.
Wie groß sollte der Query Store sein?
Die Maximalgröße (MAX_STORAGE_SIZE_MB) hängt von Workload und gewünschter Aufbewahrungsdauer ab — als Startwert sind ein bis zwei Gigabyte für die meisten Datenbanken großzügig, sehr aktive Systeme brauchen mehr. Entscheidend ist, was passiert, wenn der Speicher voll läuft: Im Modus READ_ONLY hört der Query Store dann auf zu sammeln, und du verlierst die laufende Aufzeichnung. Deshalb solltest du die Größe so wählen, dass sie die gewünschte Aufbewahrungszeit (CLEANUP_POLICY mit STALE_QUERY_THRESHOLD_DAYS) komfortabel abdeckt, und den Füllstand überwachen. Ein voller, in READ_ONLY gekippter Query Store ist ein abgeschalteter Flugschreiber — genau das, was man vermeiden will.
Welche Einstellungen sind empfohlen?
Als solide Ausgangskonfiguration: OPERATION_MODE = READ_WRITE (sonst sammelt er nicht), eine großzügig dimensionierte MAX_STORAGE_SIZE_MB, die zur Aufbewahrungszeit passt, QUERY_CAPTURE_MODE = AUTO (erfasst die relevanten Abfragen und ignoriert triviale Einmal-Abfragen, schont also den Speicher), ein moderates INTERVAL_LENGTH_MINUTES für die Statistik-Aggregation (60 Minuten ist üblich) und eine STALE_QUERY_THRESHOLD-Aufbewahrung, die deinen typischen Diagnose-Horizont abdeckt. Auf sehr hoch frequentierten Systemen lohnt der QUERY_CAPTURE_MODE = CUSTOM mit Schwellenwerten, um nur die wirklich relevanten Abfragen zu erfassen. Die genauen Werte gehören an die Workload angepasst — die Defaults sind ein vernünftiger Start.
