Solucionando problemas de espera do SOS_SCHEDULER_YIELD

14

Executando nosso ERP corporativo (Dynamics AX 2012), notei que nosso ambiente de produção parecia muito mais lento que nossos sistemas de desenvolvimento.

Depois de executar as mesmas atividades nos ambientes de desenvolvimento e produção durante a execução de um rastreamento, confirmei que as consultas SQL estavam sendo executadas muito lentamente em nosso ambiente de produção em comparação ao desenvolvimento (10 a 50 vezes mais lento, em média).

No começo, eu atribuí isso ao carregamento e executei novamente as mesmas atividades no ambiente de produção fora do horário comercial e encontrei os mesmos resultados no rastreamento.

Limpei minhas estatísticas de espera no SQL Server e deixei o servidor executar sob sua carga de produção normal por um tempo e depois executei esta consulta:

WITH [Waits] AS
    (SELECT
        [wait_type],
        [wait_time_ms] / 1000.0 AS [WaitS],
        ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],
        [signal_wait_time_ms] / 1000.0 AS [SignalS],
        [waiting_tasks_count] AS [WaitCount],
        100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
        ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum]
    FROM sys.dm_os_wait_stats
    WHERE [wait_type] NOT IN (
        N'CLR_SEMAPHORE',    N'LAZYWRITER_SLEEP',
        N'RESOURCE_QUEUE',   N'SQLTRACE_BUFFER_FLUSH',
        N'SLEEP_TASK',       N'SLEEP_SYSTEMTASK',
        N'WAITFOR',          N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
        N'CHECKPOINT_QUEUE', N'REQUEST_FOR_DEADLOCK_SEARCH',
        N'XE_TIMER_EVENT',   N'XE_DISPATCHER_JOIN',
        N'LOGMGR_QUEUE',     N'FT_IFTS_SCHEDULER_IDLE_WAIT',
        N'BROKER_TASK_STOP', N'CLR_MANUAL_EVENT',
        N'CLR_AUTO_EVENT',   N'DISPATCHER_QUEUE_SEMAPHORE',
        N'TRACEWRITE',       N'XE_DISPATCHER_WAIT',
        N'BROKER_TO_FLUSH',  N'BROKER_EVENTHANDLER',
        N'FT_IFTSHC_MUTEX',  N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
        N'DIRTY_PAGE_POLL',  N'SP_SERVER_DIAGNOSTICS_SLEEP')
    )
SELECT
    [W1].[wait_type] AS [WaitType],
    CAST ([W1].[WaitS] AS DECIMAL(14, 2)) AS [Wait_S],
    CAST ([W1].[ResourceS] AS DECIMAL(14, 2)) AS [Resource_S],
    CAST ([W1].[SignalS] AS DECIMAL(14, 2)) AS [Signal_S],
    [W1].[WaitCount] AS [WaitCount],
    CAST ([W1].[Percentage] AS DECIMAL(4, 2)) AS [Percentage],
    CAST (([W1].[WaitS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgWait_S],
    CAST (([W1].[ResourceS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgRes_S],
    CAST (([W1].[SignalS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgSig_S]
FROM [Waits] AS [W1] INNER JOIN [Waits] AS [W2] ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum], [W1].[wait_type], [W1].[WaitS],
    [W1].[ResourceS], [W1].[SignalS], [W1].[WaitCount], [W1].[Percentage]
HAVING SUM ([W2].[Percentage]) - [W1].[Percentage] < 95; -- percentage threshold

Meus resultados são os seguintes:

WaitType               Wait_S  Resource_S  Signal_S  WaitCount  Percentage  AvgWait_S  AvgRes_S  AvgSig_S
SOS_SCHEDULER_YIELD   4162.52        3.64   4158.88    4450085       77.33     0.0009    0.0000    0.0009
ASYNC_NETWORK_IO       457.98      331.59    126.39     351113        8.51     0.0013    0.0009    0.0004
PAGELATCH_EX           252.94        5.14    247.80     796348        4.70     0.0003    0.0000    0.0003
WRITELOG               166.01       48.01    118.00     302209        3.08     0.0005    0.0002    0.0004
LCK_M_U                145.47      145.45      0.02        123        2.70     1.1827    1.1825    0.0002

Então, aparentemente, a maior espera é de longe o SOS_Scheduler_Yield, e eu procurei no Google e descobri que ela normalmente se relaciona com a CPU que não consegue acompanhar.

Em seguida, executei essa consulta várias vezes seguidas.

SELECT *
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255

Eu sei que deveria estar procurando agendadores com runnable_tasks_count diferente de zero ou pending_disk_io_count, mas é basicamente zero quase o tempo todo.

Devo também mencionar que o Max Degree of Parallelism foi definido como 1, uma vez que a carga de trabalho do Dynamics AX é tipicamente OLTP por natureza, e alterá-la 8 não fez muita diferença nas estatísticas de espera acima, elas se tornaram quase exatamente iguais com a mesma problemas de desempenho.

Estou meio que perdendo para onde ir daqui, basicamente tenho um SQL Server aparentemente com CPU amarrada, mas que não aguarda runnable_tasks ou IO.

Sei que o subsistema de E / S deste SQL Server não é muito bom, porque a execução do SQLIO na unidade que contém os bancos de dados reais pode levar a números bastante baixos (pense em 10 MB por segundo para certos tipos de leitura / gravação). não parece que o SQL esteja esperando por isso, devido à quantidade de memória no servidor que está armazenando em cache a maioria dos bancos de dados.

Aqui estão algumas informações do ambiente para ajudar:

Ambiente de produção:

  • servidor SQL
  • HP ProLian DL360p Gen8
  • Intel Xeon E5-2650 0 a 2.00GHz x 2 com hyperthreading (32 núcleos lógicos)
  • 184GB de memória
  • Windows Server 2012
  • 2 instâncias do SQL Server 2012 Standard (RTM, sem patch)
  • Unidades Raid 1 279GB (15k) C: unidade, contém bancos de dados e sistema operacional
  • Arquivo de Página e TempDB em unidades distintas e separadas (estado sólido)

Meu DEV:

  • Servidor SQL Server e Dynamics AX 2012 AOS hospedado pelo Hyper-V
  • Core i7 3.4ghz com hyperthreading (8 núcleos lógicos)
  • 8GB de memória
  • Windows Server 2008 R2
  • SSD para toda a VM.

Gostaria de receber qualquer contribuição sobre outras coisas para procurar.

Nicholas Peterson
fonte

Respostas:

16

Por isso, resolvi isso: os recursos de gerenciamento de energia foram ativados em nosso servidor SQL que estavam aumentando e diminuindo a frequência da CPU, mas não rápido o suficiente para atender à pequena demanda e introduziu a espera SOS_Scheduler_Yield. Depois de alterá-lo para ser executado sempre em alto desempenho, o problema desapareceu e agora as esperas são mais normais (coisas do tipo LatchIO).

Nicholas Peterson
fonte