我如何找出是什么在打击我的 SQLServer?

我的 SQLServerCPU 在今天的大部分时间里都处于90% 左右。

我不在一个位置能够重新启动它,因为它正在不断使用。

有没有可能找出 SQL 内部是什么导致了这样的 CPU 过载?

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

我已经运行了 sp _ who2,但是不确定所有内容的确切含义,以及是否有可能在这里确定可能的问题。

为了预防任何“它可能只是被使用了很多”的反应,这只是在今天从完全正常的活动水平开始。

我正在寻找在 SQL 中导致 CPU 损耗的任何方法。

183306 次浏览

每隔几秒钟运行其中一个,您将检测到高 CPU 连接。 或者: 将 CPU 存储在本地变量 WAITFORDELAY 中,比较存储的 CPU 值和当前的 CPU 值

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


select * from master..sysprocesses
order by CPU
desc

也许不是最优雅的,但是很有效,很快。

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

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

有两点需要注意:

  • 如果问题是大量的微小事务,那么我上面描述的过滤器将排除它们,您将错过这一点。
  • 此外,如果问题是一个单一的,大量的工作(如8小时的分析工作或设计不良的选择,必须交叉连接10亿行) ,那么你可能不会看到这个分析器,直到它完全完成,这取决于什么事件,你正在分析(sp: 完成 vs sp: statementcomplete)。

但是通常我从活动监视器或 sp _ who2开始。

这个查询使用 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 标识代价最高的 SQLServer 查询

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

您可以准确地找到 SQL 在每个 CPU 周期中的具体位置。但是知道在哪里寻找需要很多知识和经验。SQL 2005/2008还是2000? 幸运的是,对于2005年和更新的版本,有一些现成的解决方案。你已经从约翰 · 萨姆森的回答中得到了一些很好的指示。我想添加一个下载和安装 SQLServer 性能仪表板报告的建议。其中一些报告包括按时间或 I/O 排列的顶级查询、大多数使用的数据文件等等,您可以很快地感觉到问题出在哪里。输出是数字和图形的,所以它对初学者更有用。

我还建议使用 活跃的亚当脚本,尽管它稍微高级一些。

最后但并非最不重要的是,我建议您下载和阅读 MS SQL 客户咨询团队关于性能分析的白皮书: SQL2005等待和队列

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

你可在此找到一些有用的查询:

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

statuswait_typecpu_time字段中,您可以找到目前正在运行的 CPU 消耗最大的任务。