如何找出锤击我的SQL Server的内容?

jos*_*ley 62 sql-server performance cpu-usage

我的SQL Server CPU在今天的大部分时间里都处于90%左右.

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

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

我已经运行了SQL Profiler,但是很多事情都很难判断是否有任何特别的原因造成它.

我已经运行了sp_who2,但我不确定一切是什么意思,如果有可能在这里找出可能的问题.

为了抢先任何"它可能只是被大量使用"的回应,这只是在今天从完全正常的活动水平开始.

我正在寻找在SQL中找到导致CPU悲痛的方法.

Joh*_*som 92

此查询使用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
Run Code Online (Sandbox Code Playgroud)

有关完整说明,请参阅:如何通过CPU识别最昂贵的SQL Server查询

  • 我用过的最有用的SQL片段很长一段时间.救了我的屁股.谢谢! (3认同)

Rem*_*anu 26

我假设你在这里进行了尽职调查,确认你的CPU实际上是由SQL进程消耗的(perfmon进程类别计数器会确认这一点).通常在这种情况下,您可以获取相关性能计数器的样本,并将它们与您在正常负载运行条件下建立的基准进行比较.解决此问题后,我建议您为将来的比较建立这样的基线.

您可以准确找到每个CPU周期的SQL消耗.但知道在哪里看需要很多知识和经验.是SQL 2005/2008还是2000?幸运的是,对于2005年和更新版本,有一些现成的解决方案.你已经在John Samson的答案中得到了一些好的指针.我想添加一个建议来下载和安装SQL Server Performance Dashboard Reports.其中一些报告包括按时间或按I/O查询的最常见查询,大多数使用过的数据文件等等,您可以快速了解问题所在.输出既是数字又是图形,因此对初学者来说更有用.

我还建议使用Adam's Who is Active脚本,尽管这有点高级.

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

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

  • +1,您可以使用此链接(http://www.microsoft.com/en-us/download/details.aspx?id=29063)获取更新版本的"SQL Server Performance Dashboard Reports". (2认同)

Saa*_*dat 8

您可以在这里找到一些有用的查询:

排查 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
Run Code Online (Sandbox Code Playgroud)

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


Bra*_*adC 7

您可以运行SQL事件探查器,并按CPU或持续时间进行筛选,以便排除所有"小东西".然后,应该更容易确定您是否遇到类似特定存储过程的问题,该问题的运行时间比它应该的长得多(可能是缺失的索引或其他东西).

两个警告:

  • 如果问题是大量微小的交易,那么我上面描述的过滤器会排除它们,你会错过这个.
  • 此外,如果问题是一个单一的,大规模的工作(如8小时的分析工作或设计不良的选择,必须交叉加入10亿行),那么在完成后,你可能不会在分析器中看到这个,取决于你正在分析什么事件(sp:completed vs sp:statementcompleted).

但通常我会从Activity Monitor或sp_who2开始.


gbn*_*gbn 5

分开运行这些中的任何一个.您将检测到高CPU连接.或者:将CPU存储在本地变量WAITFOR DELAY中,比较存储的CPU值和当前CPU值

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

select * from master..sysprocesses
order by CPU
desc
Run Code Online (Sandbox Code Playgroud)

可能不是最优雅但它有效而快速.