Também pode ser útil trabalhar com um exemplo. Considere os três estados mais comuns para um trabalhador :
RUNNING = No momento, o trabalhador está sendo executado de forma não preventiva ou preventiva.
RUNNABLE = O trabalhador está pronto para executar no agendador.
SUSPENDED = O trabalhador está suspenso no momento, aguardando que um evento envie um sinal.
Trabalhadores com um estado de RUNNING
podem gerar tempo de espera. Por exemplo, se o trabalhador precisar executar código no SO em vez de no SQLOS, poderá inserir uma espera preemptiva ou externa. Durante esse tempo, ele estará executando o código em sua CPU associada, mas ainda estará gerando tempo de espera.
Trabalhadores com um estado de RUNNABLE
podem gerar tempo de espera (até onde sei). Se o trabalhador recebeu um sinal de que um recurso estava disponível, ele pode acumular o tempo de espera do sinal com base na última espera. Se o trabalhador esgotou o quantum anterior de 4 ms, pode acumular SOS_SCHEDULER_YIELD
tempo de espera.
Trabalhadores com um estado de SUSPENDED
podem gerar tempo de espera. Considere um trabalhador que está aguardando um bloqueio. Ele gerará tempo de espera até que seja sinalizado que o recurso de bloqueio necessário está disponível. Alguns trabalhadores suspensos não geram tempo de espera, incluindo aqueles não associados a uma tarefa.
Minha área de trabalho possui quatro núcleos lógicos, portanto, a contagem máxima padrão de trabalhadores é 512 . É quase certamente impraticável, mas nessa máquina eu poderia teoricamente gerar 512 segundos de tempo de espera por segundo se conseguisse fazer com que todos os trabalhadores esperassem algo de uma só vez. À medida que o número de funcionários / trabalhadores aumenta, esse número pode ficar ainda mais alto.
Você pode ver mais de um segundo de esperas por segundo, mesmo que não esteja executando nenhuma consulta no SQL Server. Na minha máquina, a seguinte consulta parece gerar entre 9 e 14 linhas:
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;
Posso tirar um instantâneo do tempo total de espera desde a última vez em que reiniciei o servidor e compará-lo com um novo total depois de esperar dez 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';
Às vezes a matemática dá certo. A última vez que o executei foi de 101339 ms. Em outras palavras, eu tive mais de 10 segundos de espera por segundo apenas nas tarefas do sistema.