78

在今天的大部分时间里,我的 SQL Server CPU 一直在 90% 左右。

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

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

我已经运行了 SQL Profiler,但是发生了这么多事情,很难判断是否有什么特别的原因导致了它。

我已经运行了 sp_who2,但不确定所有内容的确切含义以及是否可以确定此处可能存在的问题。

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

我正在寻找任何方法来找出导致 SQL 中 CPU 问题的原因。

4

6 回答 6

110

此查询使用 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

有关完整说明,请参阅:How to identify the most costly SQL Server queries by CPU

于 2009-06-03T15:01:42.197 回答
33

我在这里假设尽职调查您确认 CPU 实际被 SQL 进程消耗(perfmon 进程类别计数器会确认这一点)。通常对于这种情况,您会抽取相关性能计数器的样本,并将它们与您在正常负载操作条件下建立的基线进行比较。一旦你解决了这个问题,我建议你为将来的比较建立这样的基线。

您可以准确地找到 SQL 在每个 CPU 周期中花费的位置。但是知道在哪里看需要很多知识和经验。是 SQL 2005/2008 还是 2000?幸运的是,对于 2005 年及之后的版本,有一些现成的解决方案。您已经在 J​​ohn Samson 的回答中得到了一些很好的指导。我想添加一个下载和安装SQL Server Performance Dashboard Reports的建议。其中一些报告包括按时间或按 I/O 的热门查询、最常用的数据文件等,您可以快速了解问题所在。输出是数字和图形的,因此对初学者更有用。

我还建议使用Adam 的 Who is Active脚本,尽管它更高级一些。

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

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

于 2009-06-03T18:01:07.197 回答
9

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

调查 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

在 的字段中,status您可以找到当前正在运行的最消耗 CPU 的任务。wait_typecpu_time

于 2018-11-05T10:57:34.347 回答
7

您可以运行 SQL Profiler,并按 CPU 或持续时间进行过滤,以便排除所有“小东西”。那么确定您是否有问题(例如运行时间长得多的特定存储过程(可能是缺少索引或其他东西))应该会容易得多。

两个警告:

  • 如果问题是大量的小交易,那么我上面描述的过滤器会排除它们,你会错过这个。
  • 此外,如果问题是一个单一的、庞大的工作(比如一个 8 小时的分析工作或一个设计不良的选择,必须交叉连接十亿行),那么在它完全完成之前,您可能不会在分析器中看到它,具体取决于关于您正在分析的事件(sp:completed vs sp:statementcompleted)。

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

于 2009-06-03T14:58:52.840 回答
7

每隔几秒钟运行其中任何一个。您将检测到高 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

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

于 2009-06-03T14:29:11.747 回答
3

对于 GUI 方法,我将查看 Management 下的 Activity Monitor 并按 CPU 排序。

于 2009-06-03T14:40:33.253 回答