SQL Server 2014 的 MAXDOP 设置

Lea*_*min 8 sql-server configuration maxdop sql-server-2014

我知道这个问题已经被问过很多次了,也有答案,但是,我仍然需要更多关于这个主题的指导。

以下是来自 SSMS 的我的 CPU 的详细信息:

中央处理器

下面是数据库服务器任务管理器中的 CPU 选项卡:

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)
Run Code Online (Sandbox Code Playgroud)

我仍然看到与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
Run Code Online (Sandbox Code Playgroud)

目前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: ) (Hypervisor) 上的基于内核的许可(64 位) )

并行度的成本阈值设置为 70。CTfP 在测试相同的值后,分别设置为 70,从默认值到 25 和 50。当它是 default(5) 并且MAXDOP为 0 时,等待时间接近 70%CXPACKET

sp_blitzfirst在专家模式下执行了 60 秒,下面是结果和等待统计的输出:

sp_blitzfirst

Eri*_*ing 13

虚假

这就是等待统计报告很糟糕的原因:它没有告诉您服务器已经运行了多长时间。

我可以在你的 CPU 时间截图中看到它:55 天!

好吧,让我们做一些数学运算。

数学

一天有 86,400 秒。

SELECT (86400 * 55) seconds_in_55_days
Run Code Online (Sandbox Code Playgroud)

答案在那里? 4,752,000

您总共有452,488几秒钟的 CXPACKET。

SELECT 4752000 / 452488 AS oh_yeah_that_axis
Run Code Online (Sandbox Code Playgroud)

这给你...... 10(如果你做实际数学,它更接近9.5,这里)。

因此,虽然 CXPACKET 可能占您服务器等待的 62%,但它只发生了大约 10% 的时间。

不要管它

您已经对设置进行了正确的调整,如果您想以有意义的方式更改数字,现在是进行实际查询和索引调整的时候了。

其他注意事项

CXPACKET 可能源于偏斜并行:

在较新的版本中,它可能会显示为 CXCONSUMER:

如果没有第三方监控工具,您可能需要自己捕获等待统计信息:


Joe*_*ish 10

等待统计只是数字。如果您的服务器正在做任何事情,那么您可能会出现某种等待。此外,根据定义,必须有一个等待的百分比最高。如果没有某种规范化,这并不意味着什么。如果我正确读取任务管理器的输出,您的服务器已经运行了 55 天。这意味着您总共只有每秒 452000/(55*86400) = 0.095 等待秒CXPACKET。此外,由于您使用的是 SQL Server 2014,您的CXPACKET等待包括良性并行等待和可操作等待。有关更多详细信息,请参阅使并行等待可操作。我不会妄下结论MAXDOP根据您在此处错误设置。

我会首先测量吞吐量。这里真的有问题吗?我们无法告诉您如何做到这一点,因为这取决于您的工作量。对于 OLTP 系统,您可能会测量每秒事务数。对于 ETL,您可以测量每秒加载的行数,依此类推。

如果您确实遇到问题并且系统性能需要改进,我会在您遇到该问题时检查 CPU。如果 CPU 太高,那么您可能需要调整查询、增加服务器资源或减少活动查询的总数。如果 CPU 太低,那么您可能需要再次调整查询,增加活动查询的总数,或者可能有某种等待类型负责。

如果您确实选择查看等待统计信息,则应仅在遇到性能问题的期间查看它们。几乎在所有情况下,查看过去 55 天的全球等待统计数据都不是可行的。它给数据增加了不必要的噪音,使您的工作更加困难。

一旦您完成了适当的调查,改变可能MAXDOP会对您有所帮助。对于您这种规模的服务器,我会坚持使用MAXDOP1、2、4 或 8。我们无法告诉您哪些最适合您的工作负载。您需要在更改之前和之后监控您的吞吐量才能MAXDOP得出结论。