我如何找出重击SQL Server的原因?


70

在今天的大部分时间里,我的SQL Server CPU大约占90%。

由于它一直在使用,我无法重新启动它。

是否有可能找出SQL中导致这种CPU过载的原因?

我已经运行了SQL事件探查器,但是发生了很多事情,很难确定是否有任何特别的原因引起了它。

我已经运行了sp_who2,但是不确定所有含义到底是什么,以及是否有可能在此处确定可能的问题。

为了阻止任何“可能只是被大量使用”的响应,今天才从完全正常的活动水平开始。

我一直在寻找在SQL中导致CPU崩溃的原因。

Answers:


30

我在这里进行尽职调查,您已确认SQL进程实际上消耗了CPU(perfmon进程类别计数器将确认这一点)。通常,在这种情况下,需要对相关性能计数器进行采样,并将其与在正常负载运行条件下建立的基准进行比较。解决此问题后,建议您为以后的比较建立这样的基准。

您可以确切找到每个CPU周期在SQL上花费的位置。但是知道在哪里看需要很多知识和经验。是SQL 2005/2008还是2000?幸运的是,对于2005年及以后的版本,有几个现成的解决方案。约翰·萨姆森(John Samson)的答案已经为您提供了很好的指导。我想添加一条建议,以下载和安装SQL Server性能仪表板报告。其中一些报告包括按时间或按I / O的热门查询,最常用的数据文件等,您可以快速了解问题所在。输出既是数字的又是图形的,因此对于初学者来说更有用。

我还建议使用Adam的Who is Active脚本,尽管这要先进一些。

最后但并非最不重要的一点是,我建议您下载并阅读有关性能分析的MS SQL客户咨询团队白皮书:SQL 2005 Waits and Queues

我的建议还应该看一下I / O。如果您向服务器添加了一个浪费缓冲池的负载(即,它需要大量数据以至于它从内存中逐出了缓存的数据页),那么结果将是CPU的显着增加(听起来令人惊讶,但这是事实)。罪魁祸首通常是一个新的查询,它端对端扫描一个大表。


2
+1,您可以使用此链接(microsoft.com/en-us/download/details.aspx?id=29063)获得较新版本的SQL Server Performance Dashboard Reports
gotqn 2014年

您是否会知道为什么(即使)最新的性能仪表板也无法显示CPU故障?
Gserg

102

此查询使用DMV来识别CPU成本最高的查询

SELECT TOP 20
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
        qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
        (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
        qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM
    sys.dm_exec_query_stats AS qs
CROSS APPLY 
    sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS APPLY
    sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY 
    qs.total_worker_time DESC

有关完整的说明,请参见:如何通过CPU确定最昂贵的SQL Server查询


1
如果它的系统相关:的VLF,检查点,统计重建等
GBN

4
我使用了很长时间的最有用的SQL。救了我的屁股。谢谢!
比尔·波纳尔

7

您可以运行SQL事件探查器,并按CPU或持续时间进行过滤,以便排除所有“小东西”。然后,确定某个问题(例如特定存储的proc)的运行时间比实际运行的时间要长得多(应该是缺少索引等)应该容易得多。

两个警告:

  • 如果问题是大量的小额交易,那么我上面描述的过滤器会将它们排除在外,而您会错过这一点。
  • 另外,如果问题是单个的繁重工作(例如8小时的分析工作或设计得很差的选择必须交叉连接十亿行),则您可能无法在探查器中看到此问题,直到完全完成为止,具体取决于关于您正在分析的事件(sp:completed与sp:statementcompleted)。

但是通常我从活动监视器或sp_who2开始。


5

将其中任何一个间隔几秒钟。您将检测到CPU连接过高。或者:将存储的CPU存储在局部变量WAITFOR DELAY中,比较存储的和当前的CPU值

select * from master..sysprocesses
where status = 'runnable' --comment this out
order by CPU
desc

select * from master..sysprocesses
order by CPU
desc

可能不是最优雅的,但它会有效且快速。


嗨,谢谢你,我这样做了,它在LOGMGR_QUEUE cpu列返回20296。这个数字是多少单位?
joshcomley

4

您可以在此处找到一些有用的查询:

调查SQL Server高CPU的原因

对我来说,这很有帮助:

SELECT s.session_id,
    r.status,
    r.blocking_session_id 'Blk by',
    r.wait_type,
    wait_resource,
    r.wait_time / (1000 * 60) 'Wait M',
    r.cpu_time,
    r.logical_reads,
    r.reads,
    r.writes,
    r.total_elapsed_time / (1000 * 60) 'Elaps M',
    Substring(st.TEXT,(r.statement_start_offset / 2) + 1,
    ((CASE r.statement_end_offset
WHEN -1
THEN Datalength(st.TEXT)
ELSE r.statement_end_offset
END - r.statement_start_offset) / 2) + 1) AS statement_text,
    Coalesce(Quotename(Db_name(st.dbid)) + N'.' + Quotename(Object_schema_name(st.objectid, st.dbid)) + N'.' +
    Quotename(Object_name(st.objectid, st.dbid)), '') AS command_text,
    r.command,
    s.login_name,
    s.host_name,
    s.program_name,
    s.last_request_end_time,
    s.login_time,
    r.open_transaction_count
FROM sys.dm_exec_sessions AS s
    JOIN sys.dm_exec_requests AS r
ON r.session_id = s.session_id
    CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st
WHERE r.session_id != @@SPID
ORDER BY r.cpu_time desc

在状态字段,wait_type和cpu_time中,您可以找到当前正在运行的消耗CPU最多的任务。


3

对于GUI方法,我将查看“管理”下的“活动监视器”并按CPU进行排序。


3
希望GUI不会因加载的SQL Server盒上发生的“锁定超时”错误而超时...
gbn

当然可以,但是我建议这样做是因为我经历了以下随机字符:CPU严重!!!!我:听起来像是系统表的工作!<疯狂地写查询>不是我:不用担心,我在活动监视器中找到并杀死了罪魁祸首。
cmsjr

2
为报告生成数据的存储过程。很多联接和聚合,零散的索引。我们使用with(nolock重新编写了查询,并重建了所有索引,它不再是一个问题
。– cmsjr
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.