分配更多的CPU和RAM后,SQL Server的性能降低


33

我们在虚拟Windows 2008 R2服务器上运行SQL Server 2008 R2(10.50.1600)。将CPU从1核升级到4,将RAM从4 gb升级到10 gb后,我们注意到性能会变差。

我看到一些观察结果:

  1. 现在,运行时间少于5秒的查询现在耗时200秒以上。
  2. 使用sqlservr.exe作为罪魁祸首将CPU固定在100。
  3. 具有460万行的表上的select count(*)耗时90秒。
  4. 服务器上运行的进程没有更改。唯一的变化是增加了cpu和ram。
  5. 其他sql服务器具有静态分页文件,该服务器设置为可单独管理该文件。

有人遇到过这个问题吗?

Per sp_BlitzErik,我跑了

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

给我这些结果。

等待统计


9
上次我在SE上看到类似问题时,这是因为有人打开了VM的CPU和RAM,但是VM主机实际上没有那么多的CPU和那么多的RAM。所以我先检查一下。
user253751 '17

Answers:


55

这里发生了很多事情,其中​​大多数是相当广泛和模糊的。

  1. 2008R2 RTM于2010年4月21日问世。它完全不受支持。您需要优先考虑大约3年前才发布的最新Service Pack。这样一来,如果您遇到奇怪的错误或其他问题,您将受到保护。头部在这里找出你需要下载的内容。

  2. 由于您添加了vCPU(从1到4)并且没有更改任何设置,因此查询现在可以并行进行。我知道这听起来会更快,但是请稍等!

  3. 您可能添加了RAM,但可能没有更改“最大服务器内存”,因此服务器可以利用它。

  4. 找出您的服务器正在等待什么。我正在研究的一个开源项目提供了免费的脚本来帮助您评估SQL Server。如果您想尝试一下,请直接过去

您将想要获取sp_BlitzFirst来查看服务器的等待状态。您可以通过几种方式运行它。

这将向您显示服务器自启动以来一直在等待什么。

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

这将在30秒的窗口中显示您正在等待什么查询。

EXEC dbo.sp_BlitzFirst @Seconds = 30, @ExpertMode = 1;

一旦弄清楚正在等待什么查询(那里有大量有关等待统计的信息),就可以开始进行更改以使事情得到控制。

如果您看到它们正在等待CXPACKET,则表示您的查询正在并行进行,并且可能会相互干扰。如果您达到此目标,则可能需要考虑将“并行性”的“成本阈值”提高到50,并可能将MAXD​​OP降低到2。

完成此步骤后,您便想使用诸如sp_WhoIsActive或sp_BlitzWho之类的东西(后者在前面的GitHub存储库中)来开始捕获查询计划。除了等待统计信息外,它们还是找出问题所在的最重要内容之一。

您可能还想查看Jonathan Kehayias撰写的有关VMWare Counters的文章,以了解有关SQL Server的信息。

更新资料

回顾等待统计数据,男孩是他们很奇怪。CPU肯定有问题。您的服务器通常无聊,但是当事情变热时,事情就会变糟。我会尽力将其分解。

  1. 您正在打一个叫的毒药等待THREADPOOL。您没有很多,但这很有意义,因为您的服务器不是非常活跃。一分钟后,我将解释原因。

  2. 你有很长的平均等待SOS_SCHEDULER_YIELDCXPACKET。您使用的是VM,因此要确保SQL Server有保留,或者该框没有被严重超额使用。一个吵闹的邻居真的会毁了你在这里的日子。您还将要确保服务器/ VM guest虚拟机/ VM主机未在“平衡电源”模式下运行。这会使您的CPU降到不必要的低速运行,并且不会立即恢复到全速运行。

  3. 他们如何搭配?使用4个CPU,您有512个工作线程。请记住,一个CPU的使用相同的,但是现在您的查询可以并行进行,因此它们可以消耗更多的工作线程。在您的情况下,并行查询的每个并行分支有4个线程。

并行的是什么?最有可能的一切。并行性的默认“成本阈值”为5。该数字在90年代后期的某个类似桌面上工作时成为默认值。

坚果

诚然,您的硬件比大多数笔记本电脑都要小,但您仍然领先于此。

当大量并行查询开始时,您将用完这些工作线程。发生这种情况时,查询只是在等待线程开始。这也是需要解决的SOS_SCHEDULER_YIELD问题。查询正在逐步退出CPU,并且很长一段时间都没有恢复。我看不到任何阻塞等待,因此您很可能只是将所有查询都塞在了查询内并行等待中。

你能做什么?

  1. 确保平衡电源模式下没有任何东西
  2. 将MAXD​​OP更改为2
  3. 将并行性的成本阈值更改为50
  4. 按照上面的Jon K.文章验证VM运行状况
  5. 使用调用的脚本sp_BlitzIndex来查找任何缺少的索引请求。

有关更彻底的故障排除,请查看我为Google写白皮书,其中介绍了云计算中的硬件大小。

希望这可以帮助!



5

我没有指出的一件事是,由于调度,将vCPU添加到VM常常会使其变慢。

基本思想是,如果虚拟机具有4个vCPU,则虚拟机监控程序必须等待4个物理内核可用,以便可以调度所有vCPU,即使其中3个处于空闲状态。

如果主机中没有很多内核,而其他工作负载很忙,则可能导致额外的等待时间,并导致性能显着下降。

在VMware ESXi中,您可以通过“ CPU就绪”在高级图中看到它。

这是许多有关此情况及其诊断方法的真实示例的文章之一

如果VM的RAM分配大于NUMA节点,则添加更多的RAM也会导致性能突然下降。

此外,vCPU的配置(vSocket与vCore)实际上会影响某些应用程序,例如SQL Server。这是因为SQL Server本身知道NUMA(以避免相同的NUMA跨度性能下降),并且因为VMware可能会以不同的方式呈现虚拟NUMA节点。

在VMware自己的网站上的博客文章中对此进行了介绍


话虽这么说,我很高兴您在Erik的帮助下解决了这些问题,但是您可能还需要研究并考虑这些问题。


3

继续@sp_BlitzErik的回答,只是一点点帮助(不能发表评论),我收到了Pinal和Max Vernon(无法记住where)的一些查询,说明应该使用多少MAXDOP:

/*************************************************************************
Author          :   Kin Shah
Purpose         :   Recommend MaxDop settings for the server instance
Tested RDBMS    :   SQL Server 2008R2

**************************************************************************/
declare @hyperthreadingRatio bit
declare @logicalCPUs int
declare @HTEnabled int
declare @physicalCPU int
declare @SOCKET int
declare @logicalCPUPerNuma int
declare @NoOfNUMA 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

-- Report the recommendations ....
select
    --- 8 or less processors and NO HT enabled
    case 
        when @logicalCPUs < 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : ' + CAST(@logicalCPUs as varchar(3))
                --- 8 or more processors and NO HT enabled
        when @logicalCPUs >= 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : 8'
                --- 8 or more processors and HT enabled and NO NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA = 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
                --- 8 or more processors and HT enabled and NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA > 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
        else ''
        end as Recommendations

-------------------------------------------------- -------

--MAX VERNON 

/* 
   This will recommend a MAXDOP setting appropriate for your machine's NUMA memory
   configuration.  You will need to evaluate this setting in a non-production 
   environment before moving it to production.

   MAXDOP can be configured using:  
   EXEC sp_configure 'max degree of parallelism',X;
   RECONFIGURE

   If this instance is hosting a Sharepoint database, you MUST specify MAXDOP=1 
   (URL wrapped for readability)
   http://blogs.msdn.com/b/rcormier/archive/2012/10/25/
   you-shall-configure-your-maxdop-when-using-sharepoint-2013.aspx

   Biztalk (all versions, including 2010): 
   MAXDOP = 1 is only required on the BizTalk Message Box
   database server(s), and must not be changed; all other servers hosting other 
   BizTalk Server databases may return this value to 0 if set.
   http://support.microsoft.com/kb/899000
*/
SET NOCOUNT ON;

DECLARE @CoreCount int;
SET @CoreCount = 0;
DECLARE @NumaNodes int;

/*  see if xp_cmdshell is enabled, so we can try to use 
    PowerShell to determine the real core count
*/
DECLARE @T TABLE (
    name varchar(255)
    , minimum int
    , maximum int
    , config_value int
    , run_value int
);
INSERT INTO @T 
EXEC sp_configure 'xp_cmdshell';
DECLARE @cmdshellEnabled BIT;
SET @cmdshellEnabled = 0;
SELECT @cmdshellEnabled = 1 
FROM @T
WHERE run_value = 1;
IF @cmdshellEnabled = 1
BEGIN
    CREATE TABLE #cmdshell
    (
        txt VARCHAR(255)
    );
    INSERT INTO #cmdshell (txt)
    EXEC xp_cmdshell 'powershell -OutputFormat Text -NoLogo -Command "& {Get-WmiObject -namespace "root\CIMV2" -class Win32_Processor -Property NumberOfCores} | select NumberOfCores"';
    SELECT @CoreCount = CONVERT(INT, LTRIM(RTRIM(txt)))
    FROM #cmdshell
    WHERE ISNUMERIC(LTRIM(RTRIM(txt)))=1;
    DROP TABLE #cmdshell;
END
IF @CoreCount = 0 
BEGIN
    /* 
        Could not use PowerShell to get the corecount, use SQL Server's 
        unreliable number.  For machines with hyperthreading enabled
        this number is (typically) twice the physical core count.
    */
    SET @CoreCount = (SELECT i.cpu_count from sys.dm_os_sys_info i); 
END

SET @NumaNodes = (
    SELECT MAX(c.memory_node_id) + 1 
    FROM sys.dm_os_memory_clerks c 
    WHERE memory_node_id < 64
    );

DECLARE @MaxDOP int;

/* 3/4 of Total Cores in Machine */
SET @MaxDOP = @CoreCount * 0.75; 

/* if @MaxDOP is greater than the per NUMA node
    Core Count, set @MaxDOP = per NUMA node core count
*/
IF @MaxDOP > (@CoreCount / @NumaNodes) 
    SET @MaxDOP = (@CoreCount / @NumaNodes) * 0.75;

/*
    Reduce @MaxDOP to an even number 
*/
SET @MaxDOP = @MaxDOP - (@MaxDOP % 2);

/* Cap MAXDOP at 8, according to Microsoft */
IF @MaxDOP > 8 SET @MaxDOP = 8;

PRINT 'Suggested MAXDOP = ' + CAST(@MaxDOP as varchar(max));

第一个脚本返回空白结果。第二个返回的建议MAXDOP = 2与@sp_BlitzErik一致。谢谢!
杰夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.