Je sais que cette question a été posée plusieurs fois et a également des réponses, mais j'ai encore besoin d'un peu plus de conseils à ce sujet.
Ci-dessous les détails de mon CPU de SSMS:
Vous trouverez ci-dessous l'onglet CPU du gestionnaire de tâches du serveur DB:
J'ai gardé le réglage de MAXDOP
à 2 en suivant la formule ci-dessous:
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)
Je constate toujours des temps d'attente élevés liés à CXPACKET
. J'utilise la requête ci-dessous pour l'obtenir:
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
Actuellement, CXPACKET
wait s'élève à 63% pour mon serveur:
J'ai fait référence à plusieurs articles sur la recommandation d'experts et j'ai également examiné MAXDOP
suggestions par Microsoft ; cependant, je ne sais pas vraiment quelle devrait être la valeur optimale pour celui-ci.
J'ai trouvé une question sur le même sujet ici cependant si je vais avec cette suggestion de Kin alors, MAXDOP
devrait être 4. Dans la même question, si nous allons avec Max Vernon, il devrait être 3.
Veuillez fournir votre précieuse suggestion.
Version: Microsoft SQL Server 2014 (SP3) (KB4022619) - 12.0.6024.0 (X64) 7 septembre 2018 01:37:51 Enterprise Edition: licence basée sur les cœurs (64 bits) sur Windows NT 6.3 (Build 9600:) (hyperviseur )
Le seuil de coût pour le parallélisme est fixé à 70. CTfP a été fixé à 70 après avoir testé le même pour des valeurs allant de 25 à 50 par défaut respectivement. Lorsqu'il était par défaut (5) et que MAXDOP
était égal à 0, le temps d'attente était proche de 70% pour CXPACKET
.
J'ai exécuté sp_blitzfirst
pendant 60 secondes en mode expert et ci-dessous est la sortie pour les résultats et les statistiques d'attente:
Voici pourquoi ce rapport de statistiques d'attente pue: il ne vous indique pas depuis combien de temps le serveur est en service.
Je peux le voir dans votre capture d'écran du temps CPU: 55 jours!
Très bien, alors faisons quelques calculs.
Il y a 86 400 secondes par jour.
SELECT (86400 * 55) seconds_in_55_days
La réponse là-bas? 4,752,000
Vous avez un total de 452,488
secondes de CXPACKET.
SELECT 4752000 / 452488 AS oh_yeah_that_axis
Ce qui vous donne ... 10 (c'est plus proche de 9,5 si vous faites des calculs réels, ici).
Ainsi, bien que CXPACKET puisse représenter 62% des attentes de votre serveur, cela ne se produit que 10% du temps.
Vous avez fait les bons réglages des paramètres, il est temps de faire des requêtes et des réglages d'index réels si vous voulez changer les chiffres de manière significative.
CXPACKET peut résulter d'un parallélisme asymétrique:
Sur les versions plus récentes, il peut apparaître en tant que CXCONSUMER:
En l'absence d'un outil de surveillance tiers, il peut être utile de capturer vous-même les statistiques d'attente:
Les statistiques d'attente ne sont que des chiffres. Si votre serveur fait quoi que ce soit, vous aurez probablement une sorte d'attente. De plus, par définition, il doit y avoir une attente qui aura le pourcentage le plus élevé. Cela ne veut rien dire sans une sorte de normalisation. Votre serveur fonctionne depuis 55 jours si je lis correctement la sortie du gestionnaire de tâches. Cela signifie que vous n'avez que 452000/(55 * 86400) = 0,095 seconde d'attente de CXPACKET
par seconde au total. De plus, étant donné que vous utilisez SQL Server 2014, vos CXPACKET
attentes incluent à la fois des attentes parallèles bénignes et des attentes exécutables. Voir Rendre les attentes d'attente du parallélisme exploitables pour plus de détails. Je ne tirerais pas de conclusion que MAXDOP
est mal réglé en fonction de ce que vous avez présenté ici.
Je voudrais d'abord mesurer le débit. Y a-t-il réellement un problème ici? Nous ne pouvons pas vous dire comment procéder car cela dépend de votre charge de travail. Pour un système OLTP, vous pouvez mesurer les transactions par seconde. Pour un ETL, vous pouvez mesurer les lignes chargées par seconde, etc.
Si vous avez un problème et que les performances du système doivent être améliorées, je vérifierais alors le processeur pendant les périodes où vous rencontrez ce problème. Si le processeur est trop élevé, vous devrez probablement régler vos requêtes, augmenter les ressources du serveur ou réduire le nombre total de requêtes actives. Si le processeur est trop faible, vous devrez peut-être à nouveau régler vos requêtes, augmenter le nombre total de requêtes actives, ou il peut y avoir un type d'attente responsable.
Si vous choisissez d'examiner les statistiques d'attente, vous ne devez les consulter que pendant la période où vous rencontrez un problème de performances. Il n'est tout simplement pas possible de consulter les statistiques mondiales d'attente au cours des 55 derniers jours dans presque tous les cas. Il ajoute un bruit inutile aux données qui rend votre travail plus difficile.
Une fois que vous avez terminé une enquête appropriée, il est possible que la modification de MAXDOP
vous aide. Pour un serveur de votre taille, je m'en tiendrai à MAXDOP
1, 2, 4 ou 8. Nous ne pouvons pas vous dire lequel sera le mieux pour votre charge de travail. Vous devez surveiller votre débit avant et après avoir modifié MAXDOP
pour tirer une conclusion.
Votre maxdop de départ doit être 4; le plus petit nombre de cœurs par nœud numa jusqu'à 8. Votre formule est incorrecte.
Un pourcentage élevé d'attentes pour un type particulier ne signifie rien. Tout dans SQL attend, donc quelque chose est toujours le plus élevé. La SEULE chose que high cxpacket attend signifie que vous avez un pourcentage élevé de parallélisme en cours. Le processeur ne semble pas élevé dans l'ensemble (au moins pour l'instantané fourni), donc ce n'est probablement pas un problème.
Avant d'essayer de résoudre un problème, définissez-le. Quel problème essayez-vous de résoudre? Dans ce cas, il semble que vous ayez défini le problème comme un pourcentage élevé d'attente de cxpacket, mais cela en soi n'est pas un problème.