Medir esperas de SQL Server durante el incidente
Calcula diferencias de contadores en el intervalo correcto y relaciona las esperas de SQL Server con las solicitudes que realmente se ralentizan.
La mayor espera acumulada del servidor no explica necesariamente por qué la aplicación se volvió lenta a las 10:15. El total puede incluir semanas de mantenimiento, tareas de fondo y una carga que ya cambió. Para estudiar un incidente corto, mide lo que cambió durante ese período y relaciónalo con las solicitudes afectadas.
Restar muestras sin reiniciar estadísticas
El script toma dos muestras separadas por diez segundos y resta contadores acumulativos. No borra estadísticas compartidas. Utiliza los permisos adecuados: normalmente VIEW SERVER STATE antes de SQL Server 2022 y VIEW SERVER PERFORMANCE STATE desde esa versión.
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 representa el intervalo y aporta su propia espera. Por eso la demostración deja visibles todas las categorías en vez de aplicar una lista de exclusiones aparentemente universal. Un recolector permanente debería guardar hora UTC, identidad del servidor y fecha de arranque del motor. Las muestras programadas por separado suelen ser preferibles a mantener una sesión esperando.
Las diferencias negativas indican que las muestras no son comparables, frecuentemente por un borrado de contadores. Un reinicio normalmente interrumpe también esta sesión y sus tablas temporales. Un recolector persistente debe detectar explícitamente que el motor ha arrancado de nuevo.
La comprobación no detecta todos los reinicios de estadísticas: un contador borrado puede superar su valor anterior antes de la segunda muestra. Coordina estas operaciones y conserva contexto. Tampoco restes max_wait_time_ms para obtener un máximo del intervalo. Si el máximo histórico sigue siendo 20 segundos, una nueva espera de 19 segundos queda oculta en esa resta.
Interpretar unidades y límites temporales
El tiempo total incluye el tiempo de señal. Restarlo obtiene el componente de espera de recurso representado por esos contadores. El tiempo de señal corresponde al retraso entre estar listo para ejecutar y ejecutar realmente. Un valor alto necesita correlación con tareas ejecutables y demanda de CPU.
Los milisegundos acumulados son tiempo de trabajadores, no tiempo de reloj. Diez tareas esperando un segundo cada una pueden aportar aproximadamente diez segundos dentro de un segundo real. El paralelismo y la concurrencia permiten que el total supere la ventana. Dividirlo por la duración del intervalo no produce un porcentaje convencional de utilización.
El número de esperas y su duración cruzan las fronteras de muestra de forma diferente. El contador aumenta cuando empieza la espera, mientras su duración terminada se registra después. Una media calculada con diferencias de un intervalo corto puede ser engañosa o indefinida. Para distribuciones precisas utiliza evidencia de eventos individuales.
Algunas categorías describen coordinación normal de fondo. Filtrarlas mejora la lectura de un panel, pero guarda las muestras originales y documenta el filtro. Una espera descartada hoy puede ser relevante en otro incidente. Además, quitar una categoría modifica los porcentajes restantes sin cambiar su trabajo real.
Seguir la espera hasta la carga
Un aumento de esperas de bloqueos orienta hacia bloqueadores, edad de transacciones y objetos afectados. PAGEIOLATCH invita a examinar lecturas de páginas y volumen de E/S solicitado. PAGELATCH trata de sincronización en memoria y no implica automáticamente comprar almacenamiento. ASYNC_NETWORK_IO también puede reflejar un cliente que consume despacio.
Durante un atasco activo consulta sys.dm_os_waiting_tasks y las solicitudes actuales. Una espera larga todavía en curso puede no aparecer completamente en las duraciones terminadas. Conserva la cadena de bloqueo y los identificadores mientras las transacciones sigan presentes.
Comprueba una mejora con una ventana de carga equivalente. Registra volumen de solicitudes, mezcla de operaciones y latencia del usuario junto con las diferencias. Tener menos esperas en un servidor menos ocupado no demuestra que la optimización ayudó. Una conclusión útil identifica la actividad responsable y muestra que la misma cantidad de trabajo se completa con menos retraso.
Referencias técnicas: Microsoft Learn: Wait statistics · Microsoft Learn: Waiting tasks.