Sei que essa pergunta já foi feita várias vezes e também tem respostas, 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 servidor DB:
Eu mantive a configuração de MAXDOP
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 tempos de espera altos relacionados a 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, a CXPACKET
espera é de 63% para o meu servidor:
Mencionei vários artigos sobre a recomendação de especialistas e também examinei as MAXDOP
sugestões da Microsoft ; no entanto, não tenho muita certeza de qual deve ser o valor ideal para este.
Eu encontrei uma pergunta sobre o mesmo tópico aqui, no entanto, se eu seguir 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 sugestão valiosa.
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 como 70. O CTfP foi definido como 70 após testar o mesmo para valores que variam de padrão a 25 e 50, respectivamente. Quando era o padrão (5) e MAXDOP
era 0, o tempo de espera era próximo a 70% CXPACKET
.
Eu executei sp_blitzfirst
por 60 segundos no modo expert e abaixo está a saída para descobertas e estatísticas de espera:
fonte
Respostas:
Falso
Eis por que esse relatório de estatísticas de espera fede: Ele não informa quanto tempo o servidor está ativo.
Eu posso vê-lo na sua captura de tela do tempo da CPU: 55 dias!
Tudo bem, então vamos fazer algumas contas.
Matemática
Existem 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, enquanto o CXPACKET pode ser 62% das esperas do seu servidor, isso acontece apenas 10% das vezes.
Deixe Sozinho
Você fez os ajustes corretos nas configurações; é hora de fazer a consulta real e o ajuste do índice, se você quiser alterar os números de maneira significativa.
Outras considerações
CXPACKET pode surgir do paralelismo distorcido:
Nas versões mais recentes, pode aparecer como CXCONSUMER:
Na ausência de uma ferramenta de monitoramento de terceiros, pode valer a pena capturar as estatísticas de espera por conta própria:
fonte
Estatísticas de espera são apenas números. Se o seu servidor estiver fazendo alguma coisa, provavelmente haverá algum tipo de espera. Além disso, por definição, deve haver uma espera que terá o maior percentual. Isso não significa nada sem algum tipo de normalização. Seu servidor está em funcionamento há 55 dias se eu estiver lendo a saída do gerenciador de tarefas corretamente. Isso significa que você só tem 452000 / (55 * 86400) = 0,095 segundos de espera
CXPACKET
por segundo no total. Além disso, como você está no SQL Server 2014, suasCXPACKET
esperas incluem esperas paralelas benignas e esperas acionáveis. Consulte Tornando o paralelismo aguardável acionável para obter mais detalhes. Eu não chegaria a uma conclusãoMAXDOP
incorreta com base no que você apresentou aqui.Eu avaliaria primeiro a taxa de transferência. 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 transações por segundo. Para um ETL, você pode medir linhas carregadas por segundo e assim por diante.
Se você tiver um problema e o desempenho do sistema precisar ser aprimorado, eu verificaria a CPU durante os momentos em que esse problema ocorrer. Se a CPU estiver 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 você precise ajustar suas consultas novamente, aumentar o número total de consultas ativas ou pode haver algum tipo de espera responsável.
Se você optar por analisar as estatísticas de espera, deverá analisá-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 alteração
MAXDOP
o ajude. Para um servidor do seu tamanho, eu continuaria comMAXDOP
1, 2, 4 ou 8. Não podemos dizer qual será o melhor para sua carga de trabalho. Você precisa monitorar sua taxa de transferência antes e depois da alteraçãoMAXDOP
para concluir.fonte
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 espera 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 aguarda significa que você tem uma alta porcentagem de paralelismo em andamento. A CPU não parece alta em geral (pelo menos para o instantâneo fornecido), portanto, 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 porcentagem alta de espera do cxpacket, mas isso por si só não é um problema.
fonte
Acho que a pergunta mais pertinente é ... você está realmente enfrentando problemas 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 tudo o que o CX espera indica é que, se as consultas ficarem paralelas, algo que mencionarei é que talvez você deva examinar qual é o seu limite de custo para o paralelismo definido se você estiver tendo problemas com as consultas que estão paralelamente, ou seja, pequenas consultas que não realizam muito trabalho paralelo e que possivelmente as tornam mais piores, não melhores, e as consultas grandes que deveriam estar paralelas estão sendo atrasadas devido a todas as menores que estão em execução mal.
Caso contrário, você não terá problemas para tentar criar um.
fonte