Wissen

Praxis-Artikel und Buchkapitel zu SQL-Performance, Sicherheit und Hochverfügbarkeit – alle frei verfügbar.

Beratung

Festpreis-Analyse mit Bericht und Handlungsempfehlung – oder strategische Begleitung bei Architektur, Migration und Hochverfügbarkeit.

Fachbücher

Die fünfbändige Reihe „Ulis SQL-Bibliothek“ – Band 1 verfügbar. Leseprobe herunterladen!

Tools

UB.SimSQL: SQL-Server-Lastsimulator mit regelbasierten Konfigurationsempfehlungen. Lokal, ohne Cloud, ohne Abo.

Schulungen

Online-Workshops zu Performance, Sicherheit und Entwicklung – kompakt, hands-on, ohne MOC-Folienschlacht.

SQL Server Statistiken veraltet

Wenn der Optimizer auf gestern plant – und heute alles stillsteht.

Statistiken veraltet — Parameter Sniffing und Plan-Regression

Gestern 0,5 Sekunden, heute 45: Wenn der Optimizer auf falschen Zahlen plant. Diagnose, Auswege und die Query-Store-Versicherung.

Es ist Donnerstagmorgen, 06:42 Uhr. Bei der Musterwerk GmbH ruft die Frühschicht der Logistik an: Die Kommissionierungs-Maske, die seit Jahren in einer halben Sekunde antwortet, braucht heute 45 Sekunden — pro Position. Am Code hat niemand etwas geändert, das letzte Release ist drei Wochen her. Geändert hat sich nur eines: In der Nacht lief der große Quartals-Datenimport, vier Millionen neue Auftragszeilen, und hinterher hat der SQL Server brav seine Statistiken aktualisiert. Genau dabei hat er der wichtigsten Prozedur des Hauses einen neuen Ausführungsplan verpasst — und der ist für den Normalfall eine Katastrophe.

Willkommen beim unsichtbarsten aller Performance-Probleme: Hier ist nichts kaputt, nichts voll, nichts blockiert — der Server tut exakt, was er soll, nur auf Basis von Zahlen, die nicht (mehr) stimmen, oder eines Plans, der für einen anderen Fall gebaut wurde. Dieser Beitrag aus dem SQL-Server-Notarztwagen (die Triage-Übersicht liegt unter /sql-server-notarztwagen/) erklärt das Dreieck aus Statistiken, Parameter Sniffing und Plan-Regression — und zeigt dir die drei Auswege, vom gezielten Statistik-Update bis zum Plan-Forcing im Query Store.

Was bedeutet das technisch?

Der Optimizer des SQL Servers ist ein Wahrscheinlichkeitsrechner: Für jede Abfrage wählt er aus vielen möglichen Plänen den voraussichtlich billigsten — und „voraussichtlich“ basiert auf Statistiken: Histogrammen über die Datenverteilung der Spalten. Aus ihnen schätzt er, wie viele Zeilen ein Filter liefern wird, und diese Kardinalitätsschätzung entscheidet über alles Weitere: Index Seek oder Table Scan? Nested Loops oder Hash Join? Wie viel Speicher als Grant? Sind die Statistiken veraltet — etwa nach einem Massenimport —, rechnet der Optimizer mit der Welt von gestern und baut Pläne, die zur Welt von heute nicht passen.

Das zweite Puzzleteil ist Parameter Sniffing: Beim ersten Aufruf einer parametrisierten Prozedur schnüffelt der Optimizer am konkreten Parameterwert und optimiert den Plan für genau diesen Wert. Der Plan wandert in den Cache — und alle weiteren Aufrufe verwenden ihn wieder, egal welche Parameter sie mitbringen. Bei gleichmäßig verteilten Daten ist das ein Segen (eine Kompilierung statt tausend); bei schiefen Verteilungen — drei Aufträge beim Kleinkunden, drei Millionen beim Großkunden — wird der geschnüffelte Plan für die halbe Belegschaft zur Falle. Welcher Parameter zuerst kommt, entscheidet der Zufall: Deshalb ist dasselbe System mal pfeilschnell und nach dem nächsten Neustart unerträglich.

Und das dritte Teil: die Plan-Regression. Pläne fliegen regelmäßig aus dem Cache — durch Statistik-Updates (Recompile-Trigger!), Neustarts, Failover, Speicher-Druck, Upgrades. Bei jeder Neukompilierung würfelt der Optimizer neu, mit den dann aktuellen Statistiken und dem dann zufälligen ersten Parameter. Meist kommt derselbe gute Plan heraus — manchmal aber ein schlechterer, und genau das ist die Lead-Szene: Das nächtliche Statistik-Update hat die Neukompilierung ausgelöst, und der neue Plan ist eine Regression. Die drei Mechanismen greifen ineinander, und die Box trennt sie sauber:

Abgrenzung: drei Mechanismen, ein Symptom

Veraltete Statistiken — der Optimizer schätzt auf alten Zahlen und baut deshalb schlechte Pläne. Heilmittel: aktualisieren.
Parameter Sniffing — der Plan ist für den Parameter des ersten Aufrufs gebaut und passt für andere nicht. Heilmittel: je nach Fall RECOMPILE, Umbau oder Forcing.
Plan-Regression — eine Neukompilierung hat einen schlechteren Plan erzeugt als den bisherigen. Heilmittel: Ursache prüfen, notfalls den bewährten Plan per Query Store erzwingen.
Alle drei fühlen sich gleich an: gestern schnell, heute langsam — und niemand hat etwas geändert.

Der Diagnose-Pfad: das Sniffing-Szenario

Die folgende Skizze zeigt den Klassiker im Zeitraffer — und darunter die drei Auswege, die im Rest des Beitrags mit Skripten unterfüttert werden:

Erste Diagnose: konkrete Skripte

Schritt 1 — Wie alt sind die Statistiken wirklich?

— Statistik-Alter und Aenderungsvolumen

SELECT OBJECT_NAME(s.object_id) AS Tabelle,

s.name AS Statistik,

sp.last_updated AS ZuletztAktualisiert,

sp.rows AS ZeilenBeimUpdate,

sp.rows_sampled AS DavonGesampelt,

sp.modification_counter AS AenderungenSeitdem

FROM sys.stats AS s

CROSS APPLY sys.dm_db_stats_properties(s.object_id, s.stats_id) AS sp

WHERE OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1

ORDER BY sp.modification_counter DESC;

Drei Spalten erzählen die Geschichte: last_updated weit in der Vergangenheit bei hohem modification_counter heißt schlicht veraltet. Spannender ist das Verhältnis rows_sampled zu rows: Wurde eine 100-Millionen-Zeilen-Tabelle mit einem Prozent Stichprobe vermessen, kann die Statistik formal frisch und trotzdem blind für die Ausreißer sein — der Fall für ein gezieltes FULLSCAN. Und ein sehr junges last_updated auf der Problemtabelle, kombiniert mit dem plötzlichen Einbruch heute Morgen? Das ist die Signatur der Lead-Szene: Das Update selbst hat die Neukompilierung ausgelöst.

Schritt 2 — Die Regression im Query Store nachweisen

— Abfragen mit mehreren Plaenen und grosser Laufzeit-Spreizung

SELECT TOP (10)

q.query_id,

OBJECT_NAME(q.object_id) AS Prozedur,

COUNT(DISTINCT p.plan_id) AS AnzahlPlaene,

MIN(rs.avg_duration) / 1000 AS BesteAvgMs,

MAX(rs.avg_duration) / 1000 AS SchlechtesteAvgMs

FROM sys.query_store_query AS q

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

HAVING COUNT(DISTINCT p.plan_id) > 1

ORDER BY MAX(rs.avg_duration) – MIN(rs.avg_duration) DESC;

Abfragen mit mehreren Plänen und großer Spreizung zwischen bester und schlechtester Durchschnittslaufzeit sind deine Regressions-Kandidaten — die Lead-Szenen-Prozedur steht hier ganz oben, mit einem 0,5-Sekunden-Plan und einem 45-Sekunden-Plan in der Historie. Noch bequemer geht es grafisch: Der SSMS-Bericht Regressed Queries unter dem Query-Store-Knoten zeigt dieselbe Auswertung mit Plan-Vergleich per Klick. Voraussetzung ist natürlich ein aktivierter Query Store — falls der noch fehlt, ist der entsprechende GRÜN-Beitrag deine nächste Lektüre, denn ohne ihn ist jede Regressions-Diagnose Archäologie ohne Fundstücke.

Schritt 3 — Eingreifen: Update, Recompile oder Forcing

— Ausweg 1: Statistiken der Problemtabelle gezielt aktualisieren

UPDATE STATISTICS dbo.Auftraege WITH FULLSCAN;

 

— Ausweg 2: Abfrage bei jedem Aufruf frisch kompilieren

SELECT … FROM dbo.Auftraege WHERE KundenNr = @KundenNr

OPTION (RECOMPILE);

 

— Ausweg 3: bewaehrten Plan per Query Store erzwingen

EXEC sp_query_store_force_plan @query_id = 4711, @plan_id = 42;

— Aufheben spaeter mit: sp_query_store_unforce_plan

Die häufigsten Ursachen — und was du dagegen tust

1. Auto Update ist zu träge für deine Tabellen

Das automatische Statistik-Update springt erst an, wenn sich „genug“ geändert hat — und auf alten Kompatibilitätsgraden hieß „genug“: 20 Prozent der Tabelle. Bei einer 50-Millionen-Zeilen-Tabelle sind das zehn Millionen Änderungen, bevor der Server reagiert; bis dahin plant er munter auf Museumszahlen. Seit Compatibility Level 130 gilt eine dynamische Schwelle, die mit der Tabellengröße sinkt — Grund genug, den Kompatibilitätsgrad alter Datenbanken zu prüfen. Aber selbst die moderne Schwelle ist ein Sicherheitsnetz, kein Wartungsplan: Wer nach Massenimporten ein gezieltes UPDATE STATISTICS in den Import-Job einbaut und eine reguläre Statistik-Wartung fährt, wartet gar nicht erst, bis das Netz greift.

2. Klassisches Sniffing — der atypische erste Aufruf

Das Szenario aus der Skizze: Der zufällige erste Aufruf nach einer Neukompilierung prägt den Plan für alle. Die Werkzeugwahl hängt vom Aufrufmuster ab: Läuft die Abfrage selten mit extrem unterschiedlichen Parametern (Suchmasken, Reports), ist OPTION (RECOMPILE) ehrlich und billig. Läuft sie hochfrequent, lohnt der Umbau: OPTIMIZE FOR mit einem repräsentativen Wert, getrennte Code-Pfade für Klein- und Großfälle — oder auf aktuellen Versionen die eingebaute Hilfe der Parameter Sensitive Plan Optimization (ab SQL Server 2022), die für stark schiefe Parameter mehrere Plan-Varianten parallel vorhält. Was nicht hilft: hoffen, dass beim nächsten Neustart zufällig der richtige Parameter zuerst kommt.

3. Das Ascending-Key-Problem — die Gegenwart fehlt im Histogramm

Die Spezialität von Datums- und ID-Spalten: Neue Zeilen landen am oberen Ende — jenseits des letzten Histogramm-Schritts. Fragt die Anwendung nach „Aufträge von heute“, schätzt der Optimizer auf Basis der alten Statistik: praktisch null Zeilen — und baut einen Mini-Plan für eine Abfrage, die in Wahrheit zehntausende Zeilen liefert. Das Muster erkennst du an Abfragen auf aktuelle Zeiträume, die im Plan absurd niedrige geschätzte Zeilenzahlen zeigen. Moderne Kardinalitätsschätzer entschärfen das Problem teilweise; die robuste Therapie bleibt, die Statistiken der betroffenen Spalten häufiger zu aktualisieren — notfalls stündlich per Job, das kostet auf einer einzelnen Statistik fast nichts.

4. Die Stichprobe ist zu klein — frisch, aber blind

Der Befund aus Schritt eins: rows_sampled ist nur ein Bruchteil von rows. Bei gleichmäßigen Daten kein Problem — bei schiefen Verteilungen übersieht die Stichprobe genau die Ausreißer, um die es geht: den einen Großkunden, die eine Massen-Kategorie. Die Statistik ist dann formal aktuell und trotzdem falsch. Therapie: für die betroffenen Statistiken UPDATE STATISTICS … WITH FULLSCAN — und damit das nicht bei der nächsten automatischen Aktualisierung wieder verwässert, auf neueren Versionen PERSIST_SAMPLE_PERCENT = ON setzen, das die Abtastrate festschreibt. Gezielt auf Problemfälle, nicht als Gießkanne: FULLSCAN über eine Multi-Terabyte-Datenbank ist Ressourcen-Folklore.

5. Regression nach Wartung, Failover oder Upgrade

Jedes Ereignis, das den Plan-Cache leert oder Neukompilierungen auslöst, ist ein Regressions-Risiko: das nächtliche Statistik-Update (Lead-Szene), der Failover aufs Replica, das Einspielen eines CU, und ganz besonders Upgrades mit Wechsel des Kompatibilitätsgrads — denn damit wechselt auch der Kardinalitätsschätzer, und der rechnet manche Abfragen schlicht anders. Die professionelle Antwort heißt Query Store: vor der Änderung aktivieren und Baseline sammeln, nach der Änderung den Regressed-Queries-Bericht abarbeiten und Ausreißer per Plan-Forcing auf den bewährten Plan nageln, bis die Ursache verstanden ist. So wird aus dem Upgrade-Roulette ein kontrollierter Prozess — die Details liefert der Query-Store-Beitrag der GRÜN-Stufe.

Was du auf keinen Fall tun solltest

  • Nicht: DBCC FREEPROCCACHE als Universalmedizin feuern. Ja, der gekippte Plan ist danach weg — zusammen mit tausend gesunden, und der ganze Server kompiliert das Tagesgeschäft neu. Gezielt geht das pro Plan, und seit es den Query Store gibt, ist der Rundumschlag schlicht Faulheit.
  • Nicht: OPTION (RECOMPILE) flächendeckend verteilen. Als gezieltes Werkzeug für ein paar Parameter-Chamäleons: gut. Als Standard-Hint in jeder Prozedur: ein CPU-Dauerbrand, der die Kompilier-Last vervielfacht und nebenbei den Query Store mit Einmal-Plänen flutet.
  • Nicht: Auto Update Statistics abschalten, „weil es tagsüber stört“. Wer das Sicherheitsnetz kappt, plant bald komplett auf Museumszahlen. Wenn die synchronen Updates im Tagesgeschäft stören, ist AUTO_UPDATE_STATISTICS_ASYNC die richtige Stellschraube — nicht der Aus-Schalter.
  • Nicht: Geforcte Pläne forcen und vergessen. Plan-Forcing ist ein Pflaster, kein Organersatz. Daten ändern sich, und der heute perfekte Plan kann in einem Jahr die Bremse sein. Jeder geforcte Plan gehört auf eine Wiedervorlage-Liste mit Datum und Grund.
  • Die drei häufigsten Anfängerfehler

    1. Bei „plötzlich langsam“ sofort an Hardware oder Indizes denken — statt zu fragen, ob ein Plan gekippt ist. Die Signatur ist unverkennbar: gleiche Abfrage, gleiches Datenvolumen, zehnfache Laufzeit.
    2. Den Server neu starten und sich freuen, dass es wieder läuft. Der Neustart hat nur neu gewürfelt — diesmal zufällig richtig. Das Problem kommt wieder, und die Beweise sind weg.
    3. Den Query Store erst aktivieren wollen, wenn das Problem da ist. Er ist ein Flugschreiber: Er muss vor dem Absturz laufen, sonst zeichnet er nichts auf.

    Nachsorge: Damit es nicht wiederkommt

    Drei strukturelle Maßnahmen nach dem akuten Fall: Erstens, eine geplante Statistik-Wartung etablieren — Ola Hallengrens IndexOptimize mit Statistik-Pflege ist der De-facto-Standard, ergänzt um gezielte Updates direkt nach Massenimporten. Wie Statistik- und Index-Wartung zusammenspielen (und warum ein Index-Rebuild die Statistik gratis mitliefert, REORGANIZE aber nicht), steht im Index-Wartungs-Beitrag der GRÜN-Stufe. Zweitens, den Query Store auf jeder Produktions-Datenbank aktivieren — als Flugschreiber für Pläne und als Werkzeugkasten gegen Regressionen. Drittens, geforcte Pläne und Spezial-Hints inventarisieren: eine simple Liste mit Abfrage, Datum, Grund und Wiedervorlage-Termin verhindert, dass die Pflaster von heute die Altlasten von morgen werden.

    Vertiefung in der Buchreihe

    Kardinalitätsschätzung, Plan-Mechanik und sniffing-resistenter Code füllen in der Buchreihe „SQL Server in der Praxis“ eigene Kapitel — alle Bände in der Übersicht auf der SQL-Pillar-Seite unter /sql-server/.

    Empfohlene Bände

    Band 1: Performance & Troubleshooting — Statistiken und Histogramme im Detail, Kardinalitätsschätzer alt und neu, Plan-Cache-Mechanik, Query Store von der Aktivierung bis zur Forcing-Strategie.
    Band 5: SQL Server für Entwickler — Code, der dem Optimizer hilft statt ihn auszutricksen: Parametrisierungs-Patterns, der richtige Umgang mit RECOMPILE und OPTIMIZE FOR, und warum ORM-generierte Abfragen so oft Sniffing-Opfer sind.

    Verwandte Notfälle im Notarztwagen

    Schätzfehler strahlen in viele Richtungen aus — diese Beiträge aus dem Cluster lohnen den Blick:

  • CPU dauerhaft bei 100 Prozent (/sql-server-cpu-100-prozent/) — der gekippte Plan ist einer der häufigsten CPU-Brandstifter: Wenn nach der Regression alle Kerne glühen, ist das die akute Fortsetzung.
  • Index-Wartung systematisch (/sql-server-index-wartung/) — Statistik-Pflege und Index-Wartung gehören in denselben Wartungsplan: der GRÜN-Beitrag mit der Strategie dahinter.
  • Query Store aktivieren und nutzen (/sql-server-query-store/) — der Flugschreiber im Detail: Konfiguration, Berichte, Forcing-Praxis.
  • SQL Server läuft langsam (/sql-server-langsam/) — das Diagnose-Schema der GELB-Stufe, falls noch unklar ist, ob überhaupt ein Plan-Thema vorliegt.
  • Drei Wege, wenn der Plan jetzt gerade gekippt ist

    Festpreis-Analyse

    Die Performance springt unberechenbar zwischen gut und katastrophal, nach jedem Wartungswochenende zittert das Team, und niemand traut sich mehr an den Kompatibilitätsgrad? Dafür gibt es die Festpreis-Analyse: Ich werte Statistik-Zustand und Sampling-Qualität aus, identifiziere Sniffing-Kandidaten und Regressions-Muster im Query Store, prüfe Wartungsplan und Auto-Update-Konfiguration und liefere einen Bericht mit priorisierten Maßnahmen — von den Sofort-Fixes bis zur dauerhaften Statistik-Strategie. Zum vereinbarten Festpreis, ohne Stundenzähler.

    Akut-Hotline

    Wenn die zentrale Prozedur gerade jetzt im 45-Sekunden-Modus läuft und die Frühschicht wartet: anrufen. Halte einen Zugang mit VIEW-SERVER-STATE-Rechten bereit und die Antwort auf die Schlüsselfrage — was lief heute Nacht? Import, Wartung, Failover, Patch? Mit Query Store ist der gekippte Plan in Minuten identifiziert und per Forcing entschärft; ohne dauert es etwas länger, geht aber auch.

    Selbst-Diagnose-Kit

    Du willst das Dreieck aus Statistiken, Sniffing und Regression selbst beherrschen? Das Diagnose-Kit bündelt die Skripte aus diesem Beitrag — Statistik-Alters-Analyse, Regressions-Suche im Query Store, die drei Auswege als Vorlagen — als ausführbares Paket mit Auswertungshilfe und einer Entscheidungsmatrix, welcher Ausweg zu welchem Aufrufmuster passt.

    Ein letzter Tipp

    Prüfe heute zwei Dinge auf deiner wichtigsten Datenbank: Ist der Query Store aktiv? Und steht der Kompatibilitätsgrad noch auf einem Wert von vor zehn Jahren? Beides kostet je eine Abfrage und entscheidet darüber, ob du beim nächsten gekippten Plan in fünf Minuten den Beweis samt Gegenmittel hast — oder eine Woche lang raten darfst, was da eigentlich passiert ist.

    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 aktualisiere ich SQL-Server-Statistiken?

    Gezielt mit UPDATE STATISTICS Tabelle bzw. UPDATE STATISTICS Tabelle(StatistikName) — wahlweise mit WITH FULLSCAN für die vollständige Abtastung oder mit SAMPLE-Prozentsatz. Für die ganze Datenbank existiert sp_updatestats, das allerdings nur ein Mini-Sample nutzt und alles anfasst, was sich auch nur minimal geändert hat — als Akut-Werkzeug brauchbar, als Dauerstrategie zu grob. Die nachhaltige Lösung ist eine geplante Statistik-Wartung, etwa über Ola Hallengrens IndexOptimize mit aktivierter Statistik-Pflege. Wichtig: Nach einem UPDATE STATISTICS werden betroffene Pläne automatisch neu kompiliert — genau das ist oft der gewünschte Effekt.

    Was ist Parameter Sniffing?

    Beim ersten Aufruf einer parametrisierten Prozedur oder Abfrage „schnüffelt“ der Optimizer am konkreten Parameterwert und baut den Plan passend für genau diesen Wert — dann wandert der Plan in den Cache und wird für alle weiteren Aufrufe wiederverwendet, egal welche Parameter kommen. Das ist meist effizient (eine Kompilierung statt tausend), wird aber zum Problem bei schiefen Datenverteilungen: Kompiliert der Plan für einen Kleinkunden mit 3 Zeilen und kommt danach der Großkunde mit 3 Millionen, läuft die Abfrage mit einem grotesk unpassenden Plan. Sniffing ist also ein Feature mit Nebenwirkung — die Auswege stehen in diesem Beitrag.

    Wann sollte ich UPDATE STATISTICS mit FULLSCAN nutzen?

    FULLSCAN tastet die komplette Tabelle ab statt einer Stichprobe — die Statistik wird maximal genau, der Lauf entsprechend teuer. Sinnvoll ist das bei Tabellen mit schiefen Verteilungen, bei denen Stichproben die Ausreißer verfehlen, bei hartnäckigen Schätzfehlern trotz frischer Statistik und generell bei kleinen bis mittleren Tabellen, wo der Vollscan ohnehin billig ist. Bei Multi-Terabyte-Tabellen ist nächtliches FULLSCAN dagegen Ressourcenverschwendung — dort reicht meist ein erhöhtes SAMPLE, gezielt auf die kritischen Statistiken. Faustregel: FULLSCAN als gezieltes Werkzeug für Problemfälle, nicht als Gießkanne über die ganze Datenbank.

    Wie aktiviere ich Auto Update Statistics?

    Über ALTER DATABASE [DB] SET AUTO_UPDATE_STATISTICS ON — wobei die Option in fast allen Datenbanken ohnehin aktiv ist, weil sie der Standard ist. Interessanter sind die Begleitoptionen: AUTO_UPDATE_STATISTICS_ASYNC lässt die laufende Abfrage nicht auf das Update warten (auf OLTP-Systemen oft die bessere Wahl), und der Kompatibilitätsgrad entscheidet über die Auslöseschwelle — ab Compatibility Level 130 gilt eine dynamische, mit der Tabellengröße sinkende Schwelle statt der trägen alten 20-Prozent-Regel. Wichtig zu wissen: Auto Update ist ein Sicherheitsnetz, kein Ersatz für geplante Statistik-Wartung.

    Was ist Plan-Forcing im Query Store?

    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. Das 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 Ursache der Regression gehört trotzdem diagnostiziert, und geforcte Pläne gehören auf eine Wiedervorlage-Liste.

    Wie erkenne ich Plan-Regression?

    Das Erkennungszeichen ist eine Abfrage, deren Laufzeit oder CPU-Verbrauch pro Ausführung sprunghaft steigt, ohne dass sich Code oder Datenvolumen wesentlich geändert haben — meist nach einem Statistik-Update, einem Neustart, einem Failover oder einem Upgrade. Mit aktiviertem Query Store ist der Nachweis trivial: Der Bericht „Regressed Queries“ in SSMS zeigt Abfragen mit verschlechterter Performance samt Plan-Historie, und im Plan-Vergleich siehst du schwarz auf weiß, was gekippt ist (Scan statt Seek, Hash statt Loop). Ohne Query Store bleibt nur der mühsame Vergleich über dm_exec_query_stats — einer von vielen Gründen, ihn zu aktivieren.

    Wann hilft OPTION (RECOMPILE)?

    OPTION (RECOMPILE) lässt eine Abfrage bei jedem Aufruf frisch kompilieren — der Plan passt damit immer exakt zu den aktuellen Parametern, und Parameter Sniffing ist als Problem komplett ausgeschaltet. Der Preis: CPU-Kosten bei jeder einzelnen Ausführung und kein wiederverwendbarer Plan im Cache. Sinnvoll ist das Hint deshalb für Abfragen, die selten laufen, aber dramatisch unterschiedliche Parameter-Welten bedienen — der Monats-Report, die flexible Suchmaske. Für eine Prozedur, die tausendmal pro Minute feuert, ist RECOMPILE dagegen Gift: Dort sind stabile Pläne, saubere Statistiken oder gezieltes Plan-Forcing die richtigen Werkzeuge.