SQL-Server-Wartezeiten im richtigen Intervall messen
Ermitteln Sie Wartezeitdifferenzen statt Gesamtsummen und verbinden Sie die Messwerte mit den Anfragen und Verzögerungen eines konkreten Vorfalls.
Die größte Wartezeit seit Serverstart erklärt nicht zwingend, warum eine Anwendung um 10:15 langsam wurde. Die Summe kann Wochen voller Wartung, Hintergrundarbeit und längst veränderter Last enthalten. Für einen kurzen Vorfall brauchen Sie die Veränderung im passenden Zeitraum und den Bezug zu den betroffenen Anfragen.
Messungen bilden statt Zähler löschen
Das Skript nimmt zwei Momentaufnahmen im Abstand von zehn Sekunden und subtrahiert kumulative Zähler. Es löscht keine gemeinsam genutzten Statistiken. Verwenden Sie die passenden Diagnoserechte: vor SQL Server 2022 normalerweise VIEW SERVER STATE, ab 2022 VIEW SERVER PERFORMANCE STATE.
SELECT wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms
INTO #WaitBefore
FROM sys.dm_os_wait_stats;
WAITFOR DELAY '00:00:10';
SELECT
w.wait_type,
w.waiting_tasks_count - b.waiting_tasks_count AS waits_started,
w.wait_time_ms - b.wait_time_ms AS wait_ms,
w.signal_wait_time_ms - b.signal_wait_time_ms AS signal_ms,
(w.wait_time_ms - b.wait_time_ms)
- (w.signal_wait_time_ms - b.signal_wait_time_ms) AS resource_ms
INTO #WaitDelta
FROM sys.dm_os_wait_stats AS w
JOIN #WaitBefore AS b ON b.wait_type = w.wait_type;
IF EXISTS
(
SELECT 1 FROM #WaitDelta
WHERE waits_started < 0 OR wait_ms < 0 OR signal_ms < 0
)
THROW 50001, 'Counters changed incompatibly; discard this sample.', 1;
SELECT TOP (20) *
FROM #WaitDelta
WHERE wait_ms > 0
ORDER BY wait_ms DESC;
DROP TABLE #WaitDelta;
DROP TABLE #WaitBefore;
WAITFOR legt lediglich den Messabstand fest und erzeugt selbst eine Wartezeit. Deshalb lässt die Demonstration bewusst alle Kategorien sichtbar. Ein dauerhafter Collector sollte UTC-Zeitpunkte, Serveridentität und Startzeit der Datenbankengine speichern. Geplante Einzelmessungen sind dort meist geeigneter als eine dauerhaft wartende Sitzung.
Negative Differenzen zeigen, dass die Aufnahmen nicht vergleichbar sind, beispielsweise nach dem Zurücksetzen der Zähler. Ein Neustart beendet normalerweise auch die Sitzung mit den temporären Tabellen. Bei dauerhaft gespeicherten Aufnahmen müssen Sie einen neuen Engine-Start ausdrücklich erkennen.
Die einfache Prüfung erkennt nicht jede Rücksetzung: Ein gelöschter Zähler kann vor der zweiten Aufnahme bereits wieder über den alten Wert steigen. Stimmen Sie deshalb das Löschen von Statistiken organisatorisch ab und behalten Sie den Kontext der Erfassung. Subtrahieren Sie außerdem max_wait_time_ms nicht als vermeintliches Intervallmaximum. Bleibt das bisherige Maximum bei 20 Sekunden, bleibt eine neue Wartezeit von 19 Sekunden in dieser Differenz unsichtbar.
Einheiten und Zeitgrenzen berücksichtigen
Die gesamte Wartezeit enthält Signalzeit. Ihre Subtraktion ergibt den durch diese Zähler dargestellten Ressourcenanteil. Signalzeit bezeichnet den Zeitraum zwischen Ausführungsbereitschaft und tatsächlicher Ausführung. Hohe Werte sollten Sie mit ausführbaren Tasks und CPU-Nachfrage verbinden, statt daraus allein einen CPU-Engpass abzuleiten.
Summierte Millisekunden sind Worker-Zeit, keine verstrichene Uhrzeit. Zehn Tasks, die jeweils eine Sekunde warten, können innerhalb einer Sekunde ungefähr zehn Sekunden beitragen. Parallelität und gleichzeitige Anfragen erlauben daher Summen über der Länge des Messfensters. Die Division durch die Intervalllänge ergibt keine gewöhnliche Auslastungsquote.
Auch Anzahl und Dauer überschreiten Intervallgrenzen unterschiedlich. Die Anzahl steigt beim Beginn eines Wartens, dessen abgeschlossene Dauer wird später sichtbar. Eine Durchschnittsdauer aus kurzen Differenzen kann deshalb irreführen oder bei null neuen Starts nicht berechenbar sein. Für genaue Verteilungen brauchen Sie einzelne Ereignisse statt ausschließlich aggregierter Zähler.
Manche Kategorien beschreiben normale Hintergrundkoordination. Ein Filter verbessert die Lesbarkeit eines Dashboards, sollte aber dokumentiert sein. Bewahren Sie die Rohdaten auf. Eine heute ausgeblendete Kategorie kann bei einem anderen Vorfall relevant werden. Außerdem verändern ausgeblendete Kategorien den Nenner aller verbleibenden Prozentanteile.
Den Bezug zur Arbeitslast herstellen
Steigende Lock-Wartezeiten führen zur Suche nach Blockierern, alten Transaktionen und betroffenen Objekten. PAGEIOLATCH lenkt die Untersuchung auf Seitenlesevorgänge und angeforderte I/O-Mengen. PAGELATCH betrifft dagegen Synchronisation im Speicher und begründet nicht automatisch neue Speichermedien. ASYNC_NETWORK_IO kann auch durch langsames Lesen im Client entstehen.
Bei einem laufenden Stillstand ergänzen Sie sys.dm_os_waiting_tasks und aktuelle Requests. Eine lange, noch laufende Wartezeit ist möglicherweise noch nicht vollständig in den abgeschlossenen Aggregaten enthalten. Halten Sie die Blockierungskette und die beteiligten Anfragen fest, solange sie existieren.
Vergleichen Sie eine Änderung mit einem ähnlichen Lastfenster. Speichern Sie Anfragevolumen, Art der Geschäftsoperationen und vom Benutzer beobachtete Latenz neben den Differenzen. Weniger Wartezeit an einem ruhigeren Tag beweist keine Verbesserung. Überzeugend ist eine Erklärung, welche konkrete Arbeit behindert wurde und warum dieselbe Nutzlast jetzt mit weniger Verzögerung abgeschlossen wird.
Technische Referenzen: Microsoft Learn: Wait statistics · Microsoft Learn: Waiting tasks.