我知道这个问题已经被问过很多次并且也有答案,但是我仍然需要关于这个主题的更多指导。
以下是来自 SSMS 的我的 CPU 的详细信息:
下面是 DB 服务器任务管理器中的 CPU 选项卡:
我MAXDOP
通过以下公式将设置保持在 2:
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)
我仍然看到与CXPACKET
. 我正在使用以下查询来获取:
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
目前CXPACKET
,我的服务器的等待率为 63%:
我参考了多篇关于专家推荐的文章,也看了微软MAXDOP
的建议;但是,我不确定这个的最佳值应该是多少。
我在这里发现了一个关于同一主题的问题,但是如果我接受 Kin 的建议,那么MAXDOP
应该是 4。在同一个问题中,如果我们选择 Max Vernon,它应该是 3。
请提供您宝贵的建议。
版本:Microsoft SQL Server 2014 (SP3) (KB4022619) - 12.0.6024.0 (X64) Sep 7 2018 01:37:51 Enterprise Edition:Windows NT 6.3 (Build 9600:) 上基于内核的许可(64 位)(管理程序) )
并行度的成本阈值设置为 70。CTfP 已设置为 70,在测试了从默认值分别为 25 和 50 的相同值之后。当它是 default(5) 并且MAXDOP
为 0 时,等待时间接近 70% CXPACKET
。
我sp_blitzfirst
在专家模式下执行了 60 秒,下面是结果和等待统计的输出:
虚假
这就是为什么等待统计报告很糟糕的原因:它没有告诉你服务器已经运行了多长时间。
我可以在你的 CPU 时间截图中看到:55 天!
好吧,让我们做一些数学运算。
数学
一天有 86,400 秒。
那里的答案?
4,752,000
您总共有
452,488
几秒钟的 CXPACKET。这给了你...... 10(如果你做实际数学,它更接近 9.5,在这里)。
因此,虽然 CXPACKET 可能是服务器等待的 62%,但它只发生大约 10% 的时间。
不要管它
您已经对设置进行了正确的调整,如果您想以有意义的方式更改数字,是时候进行实际的查询和索引调整了。
其他注意事项
CXPACKET 可能来自倾斜的并行性:
在较新的版本上,它可能显示为 CXCONSUMER:
如果没有第三方监控工具,可能值得自己捕获等待统计信息:
等待统计数据只是数字。如果您的服务器正在做任何事情,那么您可能会出现某种等待。此外,根据定义,必须有一个等待百分比最高的等待。如果没有某种标准化,这并不意味着任何事情。如果我正确读取任务管理器的输出,您的服务器已经运行了 55 天。这意味着您总共只有 452000/(55*86400) = 0.095 秒的等待秒数
CXPACKET
。此外,由于您使用的是 SQL Server 2014,因此您的CXPACKET
等待包括良性并行等待和可操作等待。有关更多详细信息,请参阅使并行等待可操作。我不会MAXDOP
根据您在此处提供的内容得出错误设置的结论。我将首先测量吞吐量。这里真的有问题吗?我们无法告诉您如何做到这一点,因为这取决于您的工作量。对于 OLTP 系统,您可以测量每秒的事务。对于 ETL,您可能会测量每秒加载的行数,依此类推。
如果您确实有问题并且需要提高系统性能,我会在您遇到该问题时检查 CPU。如果 CPU 太高,那么您可能需要调整查询、增加服务器资源或减少活动查询的总数。如果 CPU 太低,那么您可能需要再次调整查询,增加活动查询的总数,或者可能有一些等待类型负责。
如果您确实选择查看等待统计信息,则应仅在遇到性能问题期间查看它们。在几乎所有情况下,查看过去 55 天的全球等待统计数据根本不可行。它给数据增加了不必要的噪音,使您的工作更加困难。
一旦你完成了适当的调查,改变可能
MAXDOP
会对你有所帮助。对于您大小的服务器,我会坚持使用MAXDOP
1、2、4 或 8。我们无法告诉您其中哪一个最适合您的工作负载。您需要在更改前后监控您的吞吐量MAXDOP
以做出结论。你的“开始” maxdop 应该是 4;每个 numa 节点的最小核心数最多 8 个。您的公式不正确。
特定类型的高百分比等待没有任何意义。SQL 中的一切都在等待,所以某些东西总是最高的。唯一的高 cxpacket 等待意味着你有很高的并行度。CPU 整体看起来并不高(至少对于提供的快照而言),所以可能不是问题。
在尝试解决问题之前,先定义问题。你想解决什么问题?在这种情况下,您似乎已将问题定义为 cxpacket 等待的高百分比,但这本身并不是问题。
我认为最相关的问题是......你真的遇到任何性能问题吗?如果答案是否定的,那你为什么要在没有问题的情况下寻找问题?
就像其他答案所说的那样,一切都在等待,并且所有 CX 等待都表明如果您有并行查询,我要提到的是,如果您遇到查询问题,您可能应该看看您的并行成本阈值设置为多少并行的,即没有并行执行大量工作的小查询,这可能会使它们运行得更糟,而不是更好,并且应该并行的大型查询由于所有正在运行的较小查询而被延迟不良。
如果没有那么,你没有问题停止尝试创建一个。