Eu sei que essa pergunta já foi feita várias vezes e também tem respostas para ela, mas ainda preciso de um pouco mais de orientação sobre esse assunto.
Abaixo estão os detalhes da minha CPU do SSMS:
Abaixo está a guia CPU do gerenciador de tarefas do DB Server:
Eu mantive a configuração de MAXDOP
em 2 seguindo a fórmula abaixo:
declare @hyperthreadingRatio bit
declare @logicalCPUs int
declare @HTEnabled int
declare @physicalCPU int
declare @SOCKET int
declare @logicalCPUPerNuma int
declare @NoOfNUMA int
declare @MaxDOP int
select @logicalCPUs = cpu_count -- [Logical CPU Count]
,@hyperthreadingRatio = hyperthread_ratio -- [Hyperthread Ratio]
,@physicalCPU = cpu_count / hyperthread_ratio -- [Physical CPU Count]
,@HTEnabled = case
when cpu_count > hyperthread_ratio
then 1
else 0
end -- HTEnabled
from sys.dm_os_sys_info
option (recompile);
select @logicalCPUPerNuma = COUNT(parent_node_id) -- [NumberOfLogicalProcessorsPerNuma]
from sys.dm_os_schedulers
where [status] = 'VISIBLE ONLINE'
and parent_node_id < 64
group by parent_node_id
option (recompile);
select @NoOfNUMA = count(distinct parent_node_id)
from sys.dm_os_schedulers -- find NO OF NUMA Nodes
where [status] = 'VISIBLE ONLINE'
and parent_node_id < 64
IF @NoofNUMA > 1 AND @HTEnabled = 0
SET @MaxDOP= @logicalCPUPerNuma
ELSE IF @NoofNUMA > 1 AND @HTEnabled = 1
SET @MaxDOP=round( @NoofNUMA / @physicalCPU *1.0,0)
ELSE IF @HTEnabled = 0
SET @MaxDOP=@logicalCPUs
ELSE IF @HTEnabled = 1
SET @MaxDOP=@physicalCPU
IF @MaxDOP > 10
SET @MaxDOP=10
IF @MaxDOP = 0
SET @MaxDOP=1
PRINT 'logicalCPUs : ' + CONVERT(VARCHAR, @logicalCPUs)
PRINT 'hyperthreadingRatio : ' + CONVERT(VARCHAR, @hyperthreadingRatio)
PRINT 'physicalCPU : ' + CONVERT(VARCHAR, @physicalCPU)
PRINT 'HTEnabled : ' + CONVERT(VARCHAR, @HTEnabled)
PRINT 'logicalCPUPerNuma : ' + CONVERT(VARCHAR, @logicalCPUPerNuma)
PRINT 'NoOfNUMA : ' + CONVERT(VARCHAR, @NoOfNUMA)
PRINT '---------------------------'
Print 'MAXDOP setting should be : ' + CONVERT(VARCHAR, @MaxDOP)
Ainda estou vendo altos tempos de espera relacionados ao CXPACKET
. Estou usando a consulta abaixo para obter isso:
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'BROKER_EVENTHANDLER', N'BROKER_RECEIVE_WAITFOR',
N'BROKER_TASK_STOP', N'BROKER_TO_FLUSH',
N'BROKER_TRANSMITTER', N'CHECKPOINT_QUEUE',
N'CHKPT', N'CLR_AUTO_EVENT',
N'CLR_MANUAL_EVENT', N'CLR_SEMAPHORE',
N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE',
N'DBMIRROR_WORKER_QUEUE', N'DBMIRRORING_CMD',
N'DIRTY_PAGE_POLL', N'DISPATCHER_QUEUE_SEMAPHORE',
N'EXECSYNC', N'FSAGENT',
N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX',
N'HADR_CLUSAPI_CALL', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
N'HADR_LOGCAPTURE_WAIT', N'HADR_NOTIFICATION_DEQUEUE',
N'HADR_TIMER_TASK', N'HADR_WORK_QUEUE',
N'KSOURCE_WAKEUP', N'LAZYWRITER_SLEEP',
N'LOGMGR_QUEUE', N'ONDEMAND_TASK_QUEUE',
N'PWAIT_ALL_COMPONENTS_INITIALIZED',
N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP',
N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP',
N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESOURCE_QUEUE',
N'SERVER_IDLE_CHECK', N'SLEEP_BPOOL_FLUSH',
N'SLEEP_DBSTARTUP', N'SLEEP_DCOMSTARTUP',
N'SLEEP_MASTERDBREADY', N'SLEEP_MASTERMDREADY',
N'SLEEP_MASTERUPGRADED', N'SLEEP_MSDBSTARTUP',
N'SLEEP_SYSTEMTASK', N'SLEEP_TASK',
N'SLEEP_TEMPDBSTARTUP', N'SNI_HTTP_ACCEPT',
N'SP_SERVER_DIAGNOSTICS_SLEEP', N'SQLTRACE_BUFFER_FLUSH',
N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
N'SQLTRACE_WAIT_ENTRIES', N'WAIT_FOR_RESULTS',
N'WAITFOR', N'WAITFOR_TASKSHUTDOWN',
N'WAIT_XTP_HOST_WAIT', N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG',
N'WAIT_XTP_CKPT_CLOSE', N'XE_DISPATCHER_JOIN',
N'XE_DISPATCHER_WAIT', N'XE_TIMER_EVENT')
AND [waiting_tasks_count] > 0
)
SELECT
MAX ([W1].[wait_type]) AS [WaitType],
CAST (MAX ([W1].[WaitS]) AS DECIMAL (16,2)) AS [Wait_S],
CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16,2)) AS [Resource_S],
CAST (MAX ([W1].[SignalS]) AS DECIMAL (16,2)) AS [Signal_S],
MAX ([W1].[WaitCount]) AS [WaitCount],
CAST (MAX ([W1].[Percentage]) AS DECIMAL (5,2)) AS [Percentage],
CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S],
CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S],
CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgSig_S]
FROM [Waits] AS [W1]
INNER JOIN [Waits] AS [W2]
ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum]
HAVING SUM ([W2].[Percentage]) - MAX ([W1].[Percentage]) < 95; -- percentage threshold
GO
Atualmente CXPACKET
espera é de 63% para o meu servidor:
Referi-me a vários artigos sobre a recomendação de especialistas e também analisei MAXDOP
sugestões da Microsoft ; no entanto, não tenho certeza de qual deve ser o valor ideal para este.
Eu encontrei uma pergunta sobre o mesmo tópico aqui, no entanto, se eu for com essa sugestão de Kin, MAXDOP
deve ser 4. Na mesma pergunta, se formos com Max Vernon, deve ser 3.
Por favor, forneça sua valiosa sugestão.
Versão: Microsoft SQL Server 2014 (SP3) (KB4022619) - 12.0.6024.0 (X64) 7 de setembro de 2018 01:37:51 Enterprise Edition: Licenciamento baseado em núcleo (64 bits) no Windows NT 6.3 (Build 9600: ) (Hypervisor )
O Limite de Custo para Paralelismo é definido em 70. O CTfP foi definido em 70 após testar o mesmo para valores que variam de padrão a 25 e 50, respectivamente. Quando era padrão(5) e MAXDOP
era 0, o tempo de espera era próximo de 70% para CXPACKET
.
Executei sp_blitzfirst
por 60 segundos no modo especialista e abaixo está a saída para descobertas e estatísticas de espera:
Falso
Eis por que esse relatório de estatísticas de espera fede: ele não informa quanto tempo o servidor está ativo.
Posso ver em sua captura de tela do tempo de CPU: 55 dias!
Tudo bem, então vamos fazer algumas contas.
Matemática
Há 86.400 segundos no dia.
A resposta aí?
4,752,000
Você tem um total de
452,488
segundos de CXPACKET.O que lhe dá... 10 (é mais próximo de 9,5 se você fizer contas de verdade, aqui).
Portanto, embora o CXPACKET possa ser 62% das esperas do seu servidor, ele está acontecendo apenas cerca de 10% do tempo.
Deixe-o em paz
Você fez os ajustes corretos nas configurações, é hora de fazer a consulta real e o ajuste do índice se quiser alterar os números de maneira significativa.
Outras considerações
CXPACKET pode surgir de paralelismo distorcido:
Em versões mais recentes, pode aparecer como CXCONSUMER:
Na ausência de uma ferramenta de monitoramento de terceiros, pode valer a pena capturar estatísticas de espera por conta própria:
As estatísticas de espera são apenas números. Se o seu servidor estiver fazendo alguma coisa, você provavelmente terá algum tipo de espera. Além disso, por definição, deve haver uma espera que terá a porcentagem mais alta. Isso não significa nada sem algum tipo de normalização. Seu servidor está ativo há 55 dias se eu estiver lendo a saída do gerenciador de tarefas corretamente. Isso significa que você tem apenas 452000/(55*86400) = 0,095 segundos de espera
CXPACKET
por segundo no geral. Além disso, como você está no SQL Server 2014, suasCXPACKET
esperas incluem esperas paralelas benignas e esperas acionáveis. Consulte Tornando o paralelismo acionável para obter mais detalhes. Eu não chegaria a uma conclusão queMAXDOP
está definida incorretamente com base no que você apresentou aqui.Eu mediria primeiro o rendimento. Existe realmente um problema aqui? Não podemos dizer como fazer isso porque depende da sua carga de trabalho. Para um sistema OLTP, você pode medir as transações por segundo. Para um ETL, você pode medir as linhas carregadas por segundo e assim por diante.
Se você tiver um problema e o desempenho do sistema precisar ser melhorado, eu verificaria a CPU durante os momentos em que você tiver esse problema. Se a CPU for muito alta, você provavelmente precisará ajustar suas consultas, aumentar os recursos do servidor ou reduzir o número total de consultas ativas. Se a CPU estiver muito baixa, talvez seja necessário ajustar novamente suas consultas, aumentar o número total de consultas ativas ou pode haver algum tipo de espera responsável.
Se você optar por examinar as estatísticas de espera, deverá examiná-las apenas durante o período em que estiver enfrentando um problema de desempenho. Observar as estatísticas globais de espera nos últimos 55 dias simplesmente não é acionável em quase todos os casos. Ele adiciona ruído desnecessário aos dados que dificultam seu trabalho.
Depois de concluir uma investigação adequada, é possível que a mudança
MAXDOP
o ajude. Para um servidor do seu tamanho, eu ficaria comMAXDOP
1, 2, 4 ou 8. Não podemos dizer qual deles será o melhor para sua carga de trabalho. Você precisa monitorar seu rendimento antes e depois de mudarMAXDOP
para tirar uma conclusão.Seu maxdop 'inicial' deve ser 4; menor número de núcleos por nó numa até 8. Sua fórmula está incorreta.
Alta porcentagem de esperas por um tipo específico não significa nada. Tudo no SQL espera, então algo é sempre o mais alto. A ÚNICA coisa que o cxpacket espera significa é que você tem uma alta porcentagem de paralelismo acontecendo. A CPU não parece alta no geral (pelo menos para o instantâneo fornecido), então provavelmente não é um problema.
Antes de tentar resolver um problema, defina o problema. Que problema você está tentando resolver? Nesse caso, parece que você definiu o problema como uma alta porcentagem de esperas de cxpacket, mas isso por si só não é um problema.
Acho que a pergunta mais pertinente é... você está realmente enfrentando algum problema de desempenho? Se a resposta for não, então por que você está procurando um problema quando não há um?
Como as outras respostas disseram, tudo espera, e todas as esperas do CX indicam que se você tiver consultas paralelas, algo que mencionarei é que talvez você deva verificar qual é o limite de custo para paralelismo definido SE você estiver tendo problemas com as consultas que estão em paralelo, ou seja, pequenas consultas que não estão realizando muito trabalho em paralelo e isso possivelmente está fazendo com que funcionem pior, não melhor, e grandes consultas que deveriam estar em paralelo estão sendo atrasadas por causa de todas as menores que estão sendo executadas mal.
Se não, então, você não tem problema, pare de tentar criar um.