Como os tempos de espera podem ser maiores que o tempo do relógio?

15

Quando estou rastreando esperas com sp_BlitzFirst, recebo este detalhe:

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


 -- ?>

Isso deve ler "por 20 vezes nos últimos 5 segundos?" A localização foi CLR_SEMAPHORE.

Robert Rice
fonte

Respostas:

24

As estatísticas de não espera podem (e mais frequentemente do que não) totalizam mais do que o tempo físico gasto no próprio servidor.

Imagine uma situação em que dois encadeamentos separados passem o mesmo segundo aguardando algum recurso - você teria 2 segundos de tempo de espera por 1 segundo do tempo do relógio.

Cada encadeamento tem suas próprias esperas - a mensagem está informando que 20 segundos de tempo de espera para esse recurso específico ocorreram nos últimos 5 segundos do tempo do relógio.

Ou, dito de outra maneira, cada núcleo pode executar várias consultas ao mesmo tempo e vários núcleos podem adicionar ainda mais esperas. Ou seja, a unidade é realmente thread · segundos, não segundos.

George.Palacios
fonte
8

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 RUNNINGpodem 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 RUNNABLEpodem 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_YIELDtempo de espera.

Trabalhadores com um estado de SUSPENDEDpodem 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.

Joe Obbish
fonte