SQL Server高CPU使用故障排除

翻译自:https://mssqlwiki.com/2012/10/04/troubleshooting-sql-server-high-cpu-usage/


第一件事情是确认当系统上有高CPU使用时,是否SQL Server在消耗CPU资源或者是其它应用程序或服务。

使用这个查询(https://mssqlwiki.com/2010/11/30/how-to-find-sql-server-and-system-cpu-usage-history/)来获取CPU使用历史,或者使用任务管理器,或者使用Perfmon计数器来确认。在Perfmon,Process里的%Process time也可以被使用。记住该计数器不是基于100%。它是基于处理器的数量。如果对于sqlservr.exe看到200并且系统有8个CPU,那么sqlservr.exe消耗的CPU为800中的200(只有25%)。

是否CPU峰值是由其他应用程序包括应用程序组所导致。

下一步是确定CPU消耗的是内核时间还是用户时间。

我们可以在Perfmon中使用Process的%Privileged time和%user Time计数器。任务管理器里将显示内核时间也会帮助我们理解。

内核CPU:
通常,如果内核CPU保持10%以下,是正常的。但是如果你看到内核CPU持续在30%或以上,你应该开始查看系统驱动、防病毒软件等。一些会增加内核CPU时间的已知问题:

  1. 一些防病毒软件可以导致高内核时间。临时禁止防病毒软件可以排除它。

  2. 我们可以在SQL Server 2008或者SQL Server 2005 SP3里看到高精度定时器(high resolution timer)在虚拟机由于过期的BIOS而导致高内核时间。通过打开跟踪标志8038(配置为启动参数)临时禁止高精度定时器可以证明这一点。检查BIOS更新并长期不使用8038。


高用户CPU:
在SQL Server里一些最常见的原因是:

  1. 查询执行导致了CPU峰值(最有可能是优化器采用了糟糕的计划)。

  2. 高的编译和重编译。(结构和统计信息修改,临时表的使用,重编译提示)。

  3. 系统线程消耗CPU(Ghost cleanup、Lazy writer、Resource monitor)。

  4. 运行了很多跟踪。


1. 查询执行导致CPU峰值:

查询执行花了很长时间和CPU峰值一般是因为过期的统计信息、缺少索引、服务器配置、分布式查询等导致不正确的基数预估。

当服务器正经历这个问题,运行以下链接的查询,根据CPU时间姜旭排列列出服务器上正在执行的所有查询和计划。

获取所有正在执行的语句的SQL文本和查询计划:https://mssqlwiki.com/2010/02/01/how-to-get-sql-text-and-query-plan-for-statements-which-are-executing-now/

可能是一个查询消耗大多数CPU时间或者是多个查询每个消耗CPU。查看以上查询输出的CPU时间。


    如果是单个查询或者存储过程消耗大多数CPU:

  1. 更新该查询使用的表和索引的统计信息(如果统计信息到目前为止在执行计划里Estimated rows和estimated execution大约相等。如果有大量不同的统计信息过期并且需要更新)。

  2. 识别查询是否因为参数嗅探而使用了糟糕的执行计划(如果在XML执行计划里ParameterCompiledValue和ParameterRuntimeValue不同)。参考这个链接(https://mssqlwiki.com/2012/10/08/parameter-sniffing/)链接更多关于参数嗅探。

  3. 如果更新统计信息和修复参数嗅探都不能解决这个问题,很有可能优化器由于缺少索引和正确的统计信息而不能创建有效的计划。在数据库优化向导里运行消耗CPU的查询,并应用推荐。(你可以在XML计划里找到缺失索引详情,但是DTA更有效)你可以跟着以下步骤:使用SQL Server数据库调优向导调优查询(http://sqlserverscribbles.com/2013/06/01/sql-server-database-tuning-advisor/)。

  4. 如果消耗CPU的查询时链接服务器查询,尝试修改连接服务器的安全性,以确保链接服务器用户在远程服务器上有ddl_admin或者dba/sysadmin权限。关于这个问题的更多详情,请参考:http://blogs.msdn.com/b/psssql/archive/2009/09/02/distributed-queries-remote-login-permissions-and-execution-plans.aspx。

  5. 确保优化器没有很早终止并创建糟糕的执行计划。更多详情请参考:https://mssqlwiki.com/2012/10/07/optimizer-timeout-or-optimizer-memory-abort/。

  6. 确保消耗CPU的查询没有计划向导(XML计划将有PlanGuideDB属性。sys.plan_guides里也有条目)和查询提示(index=或(option xxx join)或inner (Join Hint) join)。

  7. 确保SET选项没有改变。





    如果是多个查询或存储过程一起消耗CPU:

  1. 更新数据里的所有表和索引的统计信息。使用以下链接中的查询:对于数据库里的所有表更新索引和统计信息(https://mssqlwiki.com/2010/09/26/how-to-rebuild-index-and-update-statistics-for-all-the-tables-in-database/)。

  2. 如果更新统计信息没有帮助并且重建索引不能降低CPU,我们只有逐一调优查询。

  3. 确保大量的RAM没有导致优化器去选择无效的计划:http://support.microsoft.com/kb/2413549

  4. 确保我们没有在同时运行很多跟踪(通常来源于监控工具)。我们使用以下查询来列出所有的活跃跟踪:找出运行在SQL Server的所有Profiler跟踪(https://mssqlwiki.com/2010/04/26/how-to-find-all-the-profiler-traces-running-on-my-sql-server/)。


2. 如果系统线程正消耗大多数CPU。


  1. 如果没有SQL查询正在消耗大多数CPU,我们可以通过查询后端线程的yssprocesses输出来识别是否后端线程正在消耗大多数CPU。

    select * from sys.sysprocesses where spid<51

  2. 检查是否你碰到了一下已知问题:

  • 资源监控器(Resource Monitor)可能消耗高CPU:http://support.microsoft.com/kb/968722

  • 在SQL Server 2008或者SQL Server 2005,在一个空闲系统上Ghost Cleanup task使用100%的CPU:http://support.microsoft.com/?id=978430


3. 高编译和重编译:我不久将对高编译和重编译写篇博文。


4. 可能影响SQL Server查询性能的其他因素。


  1. Maximum degree of parallelism。确保MAX DOP适当设置,你可以遵从以下步骤:如何设置Max degree of parallelism(MAXDOP)(http://sqlserverscribbles.com/2013/06/01/how-to-set-max-degree-of-parallelism-maxdop/)

  2. 提高优先级(Priority boost)。(不要启用提高优先级)
    译者注:
    优先推进:这个设置为SQL Server提供了处理器的推动。在任务管理器中,点击进程标签,定位SQL Server的位置,然后右击它。选择“设置优先级别”。注意,SQL Server应该运行在正常的优先级别上。输入如下命令:
      Sp_configure 'priority boost', 1
      Reconfigure with override
    然后重新启动你的SQL Server。在任务管理器中察看SQL Server现在运行在什么优先级别上。它应该是在高优先级上。SQL Server应该比其他的用户进程运行优先级别要高。在专用于SQL Server的服务器上使用这个设置。

  3. 不要启用纤程模式(Fiber mode)。

  4. 调整affinity mask(消耗部分CPU)。
    译者注:
    Affinity mask: Affinity mask让你可以控制SQL Server使用哪个处理器。对于大多数情况,你不应该接触这个设置,让操作系统控制处理器关系。然而,你也许想要用这个选项来将某个处理器专门用于另一 个进程(例如,MSSearch 或者 SQL Server磁盘 IO ,以及 SQL Server的平衡)。参考基础知识资源获取更多有关这个设置的信息。

  5. TokenAndPermUserStore:http://support.microsoft.com/kb/927396

  6. CPU电源计划降低了服务器性能:http://support.microsoft.com/kb/2207548

  7. SQL Server使用.Net Framework可以导致高CPU,请参考:http://support.microsoft.com/kb/2504603