SQL Server: Warum läuft meine Abfrage plötzlich langsam?
Björn Peters
4. April 2025

Jeder DBA kennt diese Situation: Eine SQL Server langsame Abfrage lief gestern noch unauffällig und heute wartet die Anwendung plötzlich gefühlt ewig auf das Ergebnis.
Auf den ersten Blick klingt das nach einem klassischen Performance-Problem. Oft steht dann sehr schnell „der SQL Server“ im Verdacht. In der Praxis ist es aber selten so einfach. Eine SQL Server langsame Abfrage kann viele Ursachen haben: Blocking, Parameter Sniffing, veraltete Statistiken, ein anderer Ausführungsplan, IO-Probleme, Speicherdruck oder auch ein Problem außerhalb des SQL Servers.
Ich möchte in diesem Beitrag keinen vollständigen Troubleshooting-Leitfaden bis ins letzte Detail schreiben, sondern zeigen, welche typischen Ursachen ich mir bei einer plötzlich langsamen Abfrage zuerst ansehen würde und wie man etwas strukturierter an die Analyse herangehen kann.
Die Liste möglicher Ursachen ist lang und reicht von simplen Flüchtigkeitsfehlern bis zu schwer auffindbaren Infrastrukturproblemen:
- Locks oder Blocks
- Parameter Sniffing
- veraltete oder falsche Statistiken
- veränderte Ausführungspläne
- Speicher- oder IO-Engpässe
- Threadpool-Erschöpfung
- fehlende, fehlerhafte oder geänderte Indizes
- Netzwerkaussetzer oder Latenzen außerhalb des SQL Servers
- vergessene Transaktionen oder fehlende COMMIT
- Probleme bei paralleler Ausführung
- Änderungen an Konfigurationen wie MAXDOP oder Cost Threshold for Parallelism
1. Blocking, Locks und offene Transaktionen
Ein häufiger Klassiker: Eine andere Session hält gerade einen exklusiven Lock auf eine Ressource, die deine Abfrage benötigt. Das führt zu Wartezeiten, die in der Benutzeroberfläche wie „Langsamkeit“ wirken, obwohl die Abfrage selbst gar nicht unbedingt ineffizient ist.
Locks sind Schutzmechanismen, die SQL Server nutzt, um gleichzeitige Zugriffe zu koordinieren und Datenkonsistenz zu gewährleisten. Es gibt unterschiedliche Lock-Typen, etwa Shared Locks für Lesevorgänge oder Exclusive Locks für Schreibzugriffe. Wenn eine Session einen Lock hält und eine andere dieselbe Ressource benötigt, entsteht Blocking. Das macht sich bemerkbar durch blockierte Prozesse, „hängende“ Abfragen und Wartezeiten, obwohl technisch nicht zwingend eine hohe CPU- oder IO-Auslastung vorliegen muss.
Prüfen kann man das zum Beispiel mit:
SELECT *
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0;
Die DMV sys.dm_exec_requests liefert Informationen zu aktuell ausgeführten Requests und ist daher ein guter erster Einstieg, wenn man eine hängende oder plötzlich langsame Abfrage einordnen möchte.
Oder direkt über sp_WhoIsActive – mein bevorzugtes Tool für genau solche Analysen.
Ein oft übersehener Fall: Eine Anwendung startet BEGIN TRAN und vergisst das COMMIT. Die Locks bleiben dann unter Umständen deutlich länger bestehen, als man auf den ersten Blick erwarten würde.
2. Parameter Sniffing und geänderte Ausführungspläne
SQL Server speichert beim ersten Aufruf einer Stored Procedure den Ausführungsplan basierend auf den übergebenen Parametern. Wird später ein anderer Wert verwendet, kann der ursprünglich erstellte Plan ungeeignet sein, besonders dann, wenn sich die Datenverteilung stark unterscheidet. Das nennt man Parameter Sniffing.
Ein häufiger Fall: Für einen „kleinen“ Parameterwert wird ein effizienter Plan mit Index Seek erstellt. Ruft jemand die Prozedur später mit einem „großen“ Wert auf, der viel mehr Daten liefert, bleibt der alte Plan bestehen und ist plötzlich ungeeignet. Das kann zu Table Scans, längerer Laufzeit, höherem Speicherbedarf oder deutlich mehr IO führen.
Typische Anzeichen:
- gleiche Prozedur, aber stark unterschiedliche Laufzeiten je nach Parameter
- Execution Plan zeigt unerwartete Table Scans oder Nested Loops bei großer Datenmenge
- Estimated Rows stimmen nicht mit Actual Rows überein
- eine Abfrage ist mal schnell und mal langsam, ohne dass sich der Code sichtbar geändert hat
So kann man Parameter Sniffing im Execution Plan erkennen:
- im Ausführungsplan auf den Abschnitt „Parameter List“ achten
- Estimated Rows und Actual Rows vergleichen
- mit dem Query Store verschiedene Pläne einer Abfrage vergleichen
Mögliche Maßnahmen:
- OPTION (RECOMPILE) gezielt verwenden, wenn ein neuer Plan pro Ausführung sinnvoll ist
- Parameter in der Prozedur lokal neu zuweisen, wenn das Verhalten bewusst entschärft werden soll
- Query Store nutzen, um Pläne zu beobachten und in Ausnahmefällen gezielt zu forcieren
- Stored Procedures bei bekannten Mustern trennen, zum Beispiel für „kleine“ und „große“ Parameterbereiche
Wichtig ist an dieser Stelle: Parameter Sniffing ist nicht automatisch schlecht. SQL Server nutzt Parameterwerte bewusst, um gute Pläne zu erzeugen. Problematisch wird es erst dann, wenn ein Plan für eine bestimmte Datenverteilung gut passt, aber später für andere Parameterwerte deutlich schlechter funktioniert.
Gerade bei einer SQL Server langsame Abfrage, die nicht immer langsam ist, sondern nur bei bestimmten Parametern auffällt, gehört Parameter Sniffing deshalb relativ weit oben auf die Prüfliste.
3. Veraltete Statistiken oder veränderte Datenverteilung
Bei stark wachsenden Tabellen, saisonalen Daten oder sehr ungleich verteilten Werten kann es passieren, dass Statistiken nicht mehr repräsentativ sind. Die Schätzungen für Zeilenanzahl und Verteilung sind dann schlicht falsch.
Das ist besonders relevant, weil der Optimizer seine Entscheidungen auf Basis dieser Schätzungen trifft. Wenn SQL Server glaubt, dass nur wenige Zeilen verarbeitet werden müssen, tatsächlich aber sehr viele Zeilen betroffen sind, kann ein eigentlich plausibler Plan plötzlich sehr teuer werden.
Prüfen kann man das zum Beispiel mit:
SELECT
OBJECT_NAME(object_id) AS table_name,
name AS statistics_name,
STATS_DATE(object_id, stats_id) AS last_updated
FROM sys.stats
ORDER BY last_updated ASC;
Mögliche Maßnahmen:
- Statistiken gezielt aktualisieren
- bei geeigneten Fällen FULLSCAN statt Sampling prüfen
- Wartungsjobs und deren tatsächliche Wirkung kontrollieren
- bei großen Tabellen auf Datenverteilung und Änderungsrate achten
Gerade bei Statistiken sollte man nicht nur auf das Datum schauen. Eine Statistik kann alt sein und trotzdem passen. Sie kann aber auch relativ frisch sein und trotzdem ein Problem verursachen, wenn die Datenverteilung für die konkrete Abfrage ungünstig ist.
4. Ressourcenengpässe: IO, Arbeitsspeicher und Worker Threads
Nicht jede langsame Abfrage ist ein reines Query-Problem. Manchmal wartet SQL Server schlicht auf Ressourcen. Das kann Storage, Arbeitsspeicher, CPU, Netzwerk oder verfügbare Worker Threads betreffen.
- IO: Speicher-Subsysteme mit hoher Latenz oder Contention auf gemeinsam genutzten Volumes können deutliche Leistungseinbrüche verursachen.
- Memory Pressure: Wenn der Buffer Cache nicht ausreicht oder andere Prozesse Speicher wegnehmen, muss SQL Server häufiger Daten nachladen.
- Threadpool-Erschöpfung: Wenn keine Worker Threads verfügbar sind, wartet eine Anfrage, obwohl CPU oder IO auf den ersten Blick vielleicht gar nicht auffällig wirken.
Eine SQL Server langsame Abfrage kann also auch dann entstehen, wenn der eigentliche SQL-Code unverändert geblieben ist, aber die Umgebung gerade auf IO, Speicher oder Worker Threads wartet.
Wartezeiten analysieren kann man zum Beispiel mit:
SELECT *
FROM sys.dm_os_wait_stats
ORDER BY wait_time_ms DESC;
Die DMV sys.dm_os_wait_stats ist hilfreich, aber sie ist kein fertiges Diagnoseergebnis. Wait Stats zeigen, worauf SQL Server gewartet hat. Sie erklären nicht automatisch, warum diese Wartezeiten entstanden sind.
Zusätzlich kann ein Blick auf aktuell wartende Requests sinnvoll sein:
SELECT *
FROM sys.dm_exec_requests
WHERE status = 'suspended';
Gerade hier sollte man vorsichtig sein. Ein hoher Storage-Wait bedeutet nicht automatisch, dass der Storage „schuld“ ist. Es kann auch sein, dass eine schlechte Abfrage viel zu viele Daten liest und dadurch erst den Storage sichtbar belastet.
5. Fehlende, entfernte oder ineffiziente Indizes
Wenn ein Index fehlt, entfernt oder verändert wurde, kann sich ein Ausführungsplan deutlich ändern. Das sieht dann häufig so aus, als wäre die Abfrage „plötzlich“ langsam geworden, obwohl sich am SQL-Statement selbst nichts geändert hat.
Ein klassischer Fall ist ein Index, der als „vermeintlich unnötig“ gelöscht wurde, ohne vorher zu prüfen, ob er vielleicht für seltene, aber wichtige Abfragen relevant ist. Auch geänderte Spaltenreihenfolgen, ein anderer Fillfactor oder sehr einseitige Datenverteilungen können Auswirkungen auf die Performance haben.
Index-Maintenance ist dabei nur ein Teil des Themas. Rebuild oder Reorganize lösen nicht automatisch jedes Performance-Problem. Gerade bei plötzlich langsamen Abfragen ist oft interessanter, ob sich der Ausführungsplan geändert hat, ob Statistiken passen und ob ein Index für die konkrete Zugriffsmethode überhaupt sinnvoll ist.
Sinnvolle Prüfpunkte:
- wurde ein Index kürzlich gelöscht oder verändert?
- hat sich der Ausführungsplan geändert?
- passen Estimated Rows und Actual Rows zusammen?
- wird ein vorhandener Index nicht mehr genutzt?
- liefert der Query Store Hinweise auf Planwechsel?
6. Parallelismus: Wenn MAXDOP und Cost Threshold nicht zur Workload passen
SQL Server entscheidet automatisch, ob eine Abfrage parallel ausgeführt wird. Diese Entscheidung basiert unter anderem auf geschätztem Ressourcenbedarf, Kosten des Ausführungsplans und aktuellen Systemressourcen.
Probleme entstehen dann, wenn die Systemkonfiguration nicht zur Workload passt oder wenn einzelne Abfragen deutlich mehr parallele Worker verwenden, als für das Gesamtsystem sinnvoll ist. Einstellungen wie max degree of parallelism und cost threshold for parallelism sind deshalb keine Werte, die man beliebig aus einem Best-Practice-Artikel übernehmen sollte.
Die Auswirkungen können in beide Richtungen gehen: Entweder wird unnötig viel CPU verbraucht, weil zu viele parallele Threads gestartet werden, oder eine Abfrage läuft trotz hohem Datenvolumen seriell und dadurch unnötig langsam.
- zu viele parallele Abfragen können CPU und Worker Threads belasten
- zu niedrige oder unpassende Schwellenwerte können zu unnötiger Parallelisierung führen
- zu restriktive Einstellungen können sinnvolle Parallelisierung verhindern
- der passende Wert hängt von Workload, Hardware, Edition und Betriebsmodell ab
Prüfen kann man unter anderem mit sys.dm_exec_query_stats, sys.dm_exec_query_plan, Query Store und natürlich dem tatsächlichen Ausführungsplan der betroffenen Abfrage.
Auch hier gilt: Nicht sofort an MAXDOP drehen, nur weil eine Abfrage langsam ist. Erst prüfen, ob Parallelismus wirklich das Problem ist oder nur ein sichtbares Symptom.
7. Netzwerk, Tools und externe Einflüsse
Manchmal liegt die Ursache nicht in der Abfrage und auch nicht direkt im SQL Server. Gerade bei Anwendungen mit großen Resultsets, Remote-Zugriffen, VPN-Strecken oder komplexen Netzwerkpfaden kann die eigentliche Verzögerung außerhalb der Datenbank entstehen.
- DNS-Probleme, VPN-Latenz, Firewalls oder Netzwerkgeräte können seltsame Verzögerungen verursachen.
- SQL Server ist intern schnell, aber das Frontend oder ein Drittanbieter-Tool zeigt trotzdem lange Wartezeiten.
- Große Resultsets können dazu führen, dass die Abfrage im SQL Server fertig wirkt, der Client aber noch lange Daten empfängt.
- Klassischer Fehler im SSMS: Ctrl+E zeigt nur den Plan, F5 führt die Abfrage aus.
Gerade der letzte Punkt klingt banal, aber in der Praxis lohnt es sich, auch solche einfachen Dinge nicht komplett auszublenden. Nicht jede „langsame Abfrage“ ist am Ende ein tiefes Engine-Problem.
Fazit: SQL Server langsame Abfrage nicht erraten, sondern eingrenzen
Eine plötzlich langsame Abfrage ist selten mit einer einzigen Vermutung erklärt. Natürlich kann ein fehlender Index die Ursache sein. Es kann aber genauso gut Blocking, ein anderer Ausführungsplan, Parameter Sniffing, eine geänderte Datenverteilung oder ein Engpass außerhalb des SQL Servers sein.
Für mich ist wichtig, an dieser Stelle nicht zu früh an der falschen Schraube zu drehen. Erst messen, dann einordnen, dann ändern.
Wenn man sich zuerst die aktiven Requests, Blocking-Situationen, Waits, Ausführungspläne, Statistiken und die letzten Änderungen an der Umgebung ansieht, bekommt man meistens recht schnell eine Richtung. Damit ist noch nicht jedes Problem gelöst, aber man vermeidet zumindest, blind an Indexen, MAXDOP oder Serverressourcen herumzuschrauben.
AUTOR
Björn Peters
Björn arbeitet als Senior Consultant mit Schwerpunkt Microsoft Data Platform, SQL Server, PowerShell und Azure SQL. Er unterstützt Kunden bei Betrieb, Migration, Hochverfügbarkeit, Performance-Analyse und Troubleshooting.
Auf SQL aus Hamburg teilt er Erfahrungen aus realen Projekten – praxisnah, technisch und mit Blick auf stabile, nachvollziehbare Lösungen. Neben SQL Server interessiert er sich für Science-Fiction, Backen und Radfahren.
