Windows Server服务器上SQL Server的CPU占用长期在60%以上,如何找出SQL Server到底在执行什么具体的操作?
|
admin
2025年11月12日 16:54
本文热度 467
|
当 SQL Server 占用 CPU 长期超过 60% 时,通常由低效查询或资源争用引起。以下是系统化的排查步骤和工具使用指南,帮助你精准定位问题根源:
🔍 1. 确认 SQL Server 是 CPU 占用源头
- 任务管理器/性能监视器:检查
sqlservr.exe 的 CPU 占用率是否持续高于 60%15。 - PowerShell 脚本(验证是否为 SQL Server 进程):
$serverName = $env:COMPUTERNAME
$Counters = @( ("\\$serverName\Process(sqlservr*)\% User Time"), ("\\$serverName\Process(sqlservr*)\% Privileged Time") )
Get-Counter -Counter $Counters -MaxSamples 30 | ForEach { $_.CounterSamples | ForEach { [pscustomobject]@{ TimeStamp=$_.TimeStamp; Path=$_.Path; Value=([Math]::Round($_.CookedValue,3)) } } }
- 若
% User Time > 90% → SQL Server 自身问题15; - 若
% Privileged Time > 90% → 系统组件(如杀毒软件)导致5。
📊 2. 实时定位高 CPU 查询
(1) 查看正在执行的 CPU 密集型操作
SELECT TOP 10
r.session_id, r.status, r.cpu_time, r.logical_reads,
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 [执行语句],
s.login_name, s.host_name, s.program_name
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
WHERE s.is_user_process = 1
ORDER BY r.cpu_time DESC;
- 关键字段:
cpu_time(CPU 耗时)、logical_reads(逻辑读次数)、执行语句(当前运行的 SQL 片段)24810。
(2) 查询历史累计 CPU 消耗最高的语句
SELECT TOP 10
total_worker_time/1000 AS [总CPU时间(ms)],
execution_count [执行次数],
total_worker_time/execution_count/1000 AS [单次CPU均耗(ms)],
SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.text)
ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) AS [高消耗语句]
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
ORDER BY total_worker_time DESC;
- 分析重点:单次执行 CPU 时间高(>100ms)或逻辑读次数大的查询3469。
⚙️ 3. 分析底层性能瓶颈
(1) 检查 CPU 压力信号(信号等待时间)
SELECT
SUM(signal_wait_time_ms) AS [信号等待时间],
(SUM(CAST(signal_wait_time_ms AS FLOAT)) / SUM(CAST(wait_time_ms AS FLOAT)) * 100) AS [信号等待占比%]
FROM sys.dm_os_wait_stats;
- 若信号等待占比 > 25% → CPU 资源不足,需优化查询或扩容35。
(2) 调度器负载分析
SELECT scheduler_id, current_tasks_count, runnable_tasks_count
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255;
runnable_tasks_count > 10 → 大量任务排队等待 CPU,说明 CPU 过载38。
️ 4. 使用可视化工具辅助分析
- SQL Server 性能仪表板(SSMS 内置):
- 右键实例 → 报表 → 标准报表 → 性能仪表板;
- 查看 “耗费大量资源的查询” 和 “系统 CPU 使用率” 图表57。
- 缺失索引建议:仪表板会提示可能改善性能的索引(重点评估评分 >10 万的建议)7。
🔧 5. 扩展排查方向
| 检查项 | 工具/脚本 | 问题线索 |
|---|
| 阻塞链 | sys.dm_exec_requests 的 blocking_session_id 字段48 | 长时间阻塞导致 CPU 堆积 |
| 最大工作线程数耗尽 | SELECT max_workers_count FROM sys.dm_os_sys_info810 | 若线程数接近上限(如 64 位 CPU 16 核时为 704),需优化会话或扩容 |
| 参数敏感查询 (PSP) | 检查同一查询不同参数下的执行计划差异 | 数据分布不均导致低效计划 |
| 统计信息过期/缺失索引 | sys.dm_db_missing_index_details + 更新统计信息命令 | 扫描操作增多推高 CPU15 |
💎 优化建议
- 紧急止血:
- 终止异常会话:
KILL <session_id>9。
- 长期优化:
- 为高 CPU 查询创建覆盖索引,减少全表扫描;
- 启用查询存储(Query Store)持续监控性能变化;
- 升级硬件或调整
MAXDOP 限制并行度38。
💡 提示:若问题呈周期性爆发(如每日高峰),建议结合 SQL Server Profiler 或 扩展事件 (XEvent) 捕获完整负载,分析时间关联性79。
以上步骤覆盖了从实时诊断到根因分析的完整路径。优先执行步骤 2 和步骤 3,通常能快速定位具体查询;若仍无头绪,再结合调度器负载和阻塞分析扩展排查13510。
该文章在 2025/11/12 16:54:47 编辑过