Warum ist unser SQL Server langsam?
max server memory, MAXDOP, Cost Threshold, Parameter Sniffing, der Scan, den keiner erwartet hat … Man kann sich da verrückt rechnen.
Was einem SQL Server alles passieren kann.
Eine Auswahl aus der Praxis. Keiner dieser Punkte ist für sich genommen die Antwort: Welche davon zählen, zeigt erst die Untersuchung am eigenen System.
Konfiguration
- max server memory nicht gesetztDer Standardwert erlaubt SQL Server, nahezu den gesamten Arbeitsspeicher zu belegen. Betriebssystem und andere Dienste geraten unter Druck.
- MAXDOP = 0Jede parallele Abfrage darf alle Kerne nutzen. Auf großen Servern wird Parallelität dadurch teuer.
- Cost Threshold for Parallelism = 5Ein Standardwert aus einer anderen Hardware-Ära: Schon kleine Abfragen laufen parallel.
- Plancache voller Einmal-PläneAd-hoc-Abfragen füllen den Cache mit Plänen, die nie wieder verwendet werden.
- Auto Shrink eingeschaltetDie Datenbank schrumpft und wächst im Wechsel, fragmentiert Indizes und kostet I/O.
- Autogrowth in Mini-SchrittenTausende kleine Vergrößerungen: Wartezeit bei jedem Wachsen, im Log dazu sehr viele VLFs.
- Energiesparplan „Ausbalanciert“Windows taktet die CPU herunter. Abfragen laufen messbar langsamer, als die Hardware erlaubt.
- Kompatibilitätsgrad nach dem UpgradeNeue Version, altes Verhalten, oder umgekehrt: Ein anderer Cardinality Estimator erzeugt andere Pläne.
- Virenscanner auf den DatendateienDer Echtzeitscanner prüft Daten- und Logdateien bei jedem Zugriff mit.
Wartezeiten & Sperren
- PAGEIOLATCH_SHSeiten müssen vom Datenträger gelesen werden: zu wenig Speicher, zu viel Lesen oder langsamer Storage.
- CXPACKET und CXCONSUMERParallele Threads warten aufeinander. Meist ein Symptom, selten die Ursache.
- LCK_M_XSitzungen warten auf Sperren, weil irgendwo eine Transaktion zu lange festhält.
- DeadlocksZwei Transaktionen blockieren sich gegenseitig; SQL Server bricht eine davon ab.
- WRITELOGCommits warten auf das Transaktionsprotokoll: langsames Log-Laufwerk oder sehr viele kleine Transaktionen.
- RESOURCE_SEMAPHOREAbfragen warten auf Arbeitsspeicher für Sortierungen und Hash-Joins (Memory Grants).
- SOS_SCHEDULER_YIELDViel CPU-Arbeit: Threads geben den Scheduler ab und stellen sich wieder an.
- THREADPOOLKeine freien Worker-Threads mehr. Der Server wirkt eingefroren.
- ASYNC_NETWORK_IOSQL Server wartet auf den Client, der die Ergebnisse zu langsam abholt.
- Lock EscalationAus vielen Zeilensperren wird eine Tabellensperre, und alle anderen warten.
Abfragen & Pläne
- Parameter SniffingDer Plan passt zum ersten Parameterwert, aber nicht zu den folgenden.
- Unerwarteter ScanDie Abfrage liest die ganze Tabelle, obwohl sie nur wenige Zeilen braucht.
- Schätzung weit danebenDer Plan ist für eine ganz andere Datenmenge gebaut als die, die tatsächlich kommt.
- Implizite KonvertierungDie Datentypen passen nicht zusammen, und der Index lässt sich nicht gezielt nutzen.
- Funktion auf der SpalteDie Bedingung ist nicht SARGable: Statt zu suchen, muss SQL Server jede Zeile prüfen.
- Key LookupsFür jede gefundene Zeile ein zusätzlicher Sprung in den Clustered Index.
- Spills nach tempdbDer Memory Grant war zu klein. Zwischenergebnisse landen auf dem Datenträger.
- Skalare FunktionenSie werden je nach Version zeilenweise ausgeführt und verhindern Parallelität.
- TabellenvariablenÄltere Versionen schätzen sie mit einer Zeile, egal wie viele es werden.
- NOLOCK überallLiest nicht bestätigte Daten, manche doppelt, manche gar nicht, und löst das eigentliche Problem selten.
- Catch-all-AbfragenEin Plan für alle Filterkombinationen, und meist ist es ein schlechter.
- RECOMPILE als PflasterHilft gegen Sniffing, kostet aber bei jedem Aufruf CPU für die Kompilierung.
- Zeile für ZeileMengenlogik als Schleife: Tausende Einzelschritte statt einer Operation.
Indizes & Statistiken
- Missing-Index-HinweiseDer Optimizer schlägt Indizes vor. Wer sie ungeprüft anlegt, sammelt Dubletten.
- Zu viele IndizesJeder Index kostet bei jedem INSERT, UPDATE und DELETE.
- Veraltete StatistikenFalsche Verteilungsannahmen führen zu falschen Schätzungen und damit zu schlechten Plänen.
- FragmentierungOft überschätzt: Nächtliche Rebuilds lösen selten das eigentliche Problem.
- Heaps mit Forwarded RecordsTabellen ohne Clustered Index: Zeilen wandern, Lesezugriffe springen hinterher.
- Zufällige SchlüsselGUIDs als Clustered Key: Page Splits und verstreute Schreibzugriffe.
tempdb & Storage
- tempdb-KonkurrenzViele Sitzungen streiten um dieselben Verwaltungsseiten in tempdb.
- Zu viele VLFsTausende virtuelle Logdateien verlangsamen Start, Recovery und Sicherungen.
- SpeicherlatenzDer Storage antwortet um ein Vielfaches langsamer, als die Datenbank es braucht.
- Die PLE-FaustregelDer alte Grenzwert passt nicht zu heutigen Speichergrößen. Aussagekräftig ist der Verlauf.
- Alles auf einem VolumeSequenzielles Schreiben und zufälliges Lesen teilen sich dieselbe Latenz.
- Überbuchte VirtualisierungDie virtuelle Maschine wartet auf die physischen Kerne des Hosts.
Zeit & Nachtjobs
- Zeitzonen sind kein WitzDie Umrechnung pro Zeile kostet CPU, und auf einer Spalte angewendet verhindert sie Seeks.
- Lokale Zeit in der DatenbankBei der Zeitumstellung fehlt eine Stunde, oder es gibt sie doppelt.
- Nächtliche Jobs werden zu langWartung, Importe und Berichte passen nicht mehr in ihr Zeitfenster.
- Wartung im TagesgeschäftDer Rebuild überschneidet sich mit den ersten Nutzern und bremst alle aus.
Vom Rätselraten zum Befund.
- 01
Anamnese
Anwendung, Nutzung, Auffälligkeiten und bisherige Maßnahmen verstehen.
- 02
Konfiguration
Instanz, Datenbanken, Speicher und Wartung auf Plausibilität prüfen.
- 03
Kennzahlen
Wartezeiten, Ressourcen und Trends im Zusammenhang lesen.
- 04
Workload & Pläne
Die teuersten und auffälligsten Abfragen und ihre Ausführungspläne untersuchen.
- 05
Empfehlungen
Priorisiert, begründet und mit einem Weg, die Wirkung zu prüfen.
Hinter dieser Seite steht die PSG Projekt Service GmbH aus Hamburg, gegründet 1994 und seit 1998 in SQL-Server-Projekten tätig. Mehr zu Troubleshooting, Performance-Analyse und PSG MX steht auf psg-stack.com.