¿Cómo pueden los tiempos de espera ser más altos que la hora del reloj?

15

Cuando estoy rastreando esperas con sp_BlitzFirst, obtengo este detalle:

<?ClickToSeeDetails -- 
For 20 seconds over the last 5 seconds, SQL Server was waiting on this 
particular bottleneck.


 -- ?>

¿Debería eso leer "por 20 veces en los últimos 5 segundos?" El hallazgo fue CLR_SEMAPHORE.

Robert Rice
fuente

Respuestas:

24

No: las estadísticas de espera pueden (y la mayoría de las veces, totalizarán) más que el tiempo físico dedicado al servidor en sí.

Imagine una situación en la que 2 hilos separados pasan el mismo segundo esperando algún recurso: tendría 2 segundos de tiempo de espera por 1 segundo de tiempo de reloj.

Cada hilo tiene sus propias esperas: el mensaje le indica que se produjeron 20 segundos de tiempo de espera para ese recurso en particular durante los últimos 5 segundos de tiempo de reloj.

O para decirlo de otra manera, cada núcleo puede ejecutar múltiples consultas al mismo tiempo, y múltiples núcleos pueden sumar aún más esperas. Es decir, la unidad es realmente hilo · segundos, no segundos.

George.Palacios
fuente
8

También podría ser útil trabajar con un ejemplo. Considere los tres estados más comunes para un trabajador :

EN EJECUCIÓN = El trabajador se está ejecutando actualmente de forma no preventiva o preventiva.

RUNNABLE = El trabajador está listo para ejecutarse en el planificador.

SUSPENDIDO = El trabajador está suspendido actualmente, esperando que un evento le envíe una señal.

Los trabajadores con un estado de RUNNINGpueden generar tiempo de espera. Por ejemplo, si el trabajador necesita ejecutar código en el sistema operativo en lugar de en SQLOS, entonces puede ingresar una espera preventiva o externa. Durante ese tiempo, ejecutará código en su CPU asociada, pero seguirá generando tiempo de espera.

Los trabajadores con un estado de RUNNABLEpueden generar tiempo de espera (que yo sepa, siempre lo hacen). Si se indicó al trabajador que había un recurso disponible, puede acumular tiempo de espera de la señal en función de la última espera. Si el trabajador agotó su cuántica anterior de 4 ms, entonces puede acumular SOS_SCHEDULER_YIELDtiempo de espera.

Los trabajadores con un estado de SUSPENDEDpueden generar tiempo de espera. Considere un trabajador que está esperando una cerradura. Generará tiempo de espera hasta que se indique que el recurso de bloqueo que necesita está disponible. Algunos trabajadores suspendidos no generan tiempo de espera, incluidos los que no están asociados con una tarea.

Mi escritorio tiene cuatro núcleos lógicos, por lo que el conteo máximo de trabajadores predeterminado es 512 . Es casi seguro que no es práctico, pero en esta máquina, en teoría, podría generar 512 segundos de tiempo de espera por segundo si lograra que cada trabajador espere algo a la vez. A medida que aumentan los recuentos de núcleos / trabajadores, ese número puede ser aún mayor.

Puede ver más de un segundo de esperas por segundo, incluso si no está ejecutando ninguna consulta en SQL Server. En mi máquina, la siguiente consulta parece generar entre 9-14 filas:

SELECT [state], last_wait_type, wait_started_ms_ticks
FROM sys.dm_os_workers
WHERE [state] IN ('SUSPENDED', 'RUNNABLE')
AND task_address IS NOT NULL
AND wait_started_ms_ticks <> 0
AND wait_started_ms_ticks >= start_quantum;

Puedo tomar una instantánea del tiempo de espera total desde la última vez que reinicié el servidor y compararlo con un nuevo total después de esperar diez segundos:

DECLARE @start_wait_time_ms BIGINT;

SELECT @start_wait_time_ms = SUM(wait_time_ms)
FROM sys.dm_os_wait_stats
WHERE wait_type <> 'WAITFOR';

WAITFOR DELAY '00:00:10';

SELECT SUM(wait_time_ms) - @start_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type <> 'WAITFOR';

A veces las matemáticas funcionan. La última vez que lo ejecuté, el delta fue de 101339 ms. En otras palabras, tuve más de 10 segundos de espera por segundo solo de las tareas del sistema.

Joe Obbish
fuente