优先关注“CPU Time (s)”占比高的SQL,如占DB Time近20%者;重点看Per Exec超1s(尤其>5s)的SQL;结合SQL ID查执行计划稳定性、逻辑读/物理读趋势及ASH实时会话验证,避免误判硬解析、递归调用或RAC等待等根因。

SQL ordered by CPU Time 里哪些 SQL 值得优先看
只看“CPU Time (s)”列数值最大的那几条,但更要关注 CPU Time (s) 占整个报告周期 DB Time(s) 的比例。比如报告里 DB Time(s) 是 456.2,某条 SQL 的 CPU Time (s) 是 89.3,它就吃掉了近 20% 的总数据库时间——这种必须立刻查。
别被 Executions 高迷惑:一条 SQL 执行 1000 次、每次耗 0.1s CPU,总 CPU 时间才 100s;另一条执行 2 次、每次耗 60s,总 CPU 时间 120s,后者才是真瓶颈。重点盯 Per Exec 列(单位是秒),超过 1s 就算高,超过 5s 几乎肯定有问题。
-
SQL ID是后续查执行计划和历史行为的唯一入口,务必记下 - 如果
Module显示为SQL*Plus或jdbc,说明来自应用直连,要反馈给开发 - 若
Module是DBMS_SCHEDULER或PL/SQL,说明是定时任务或存储过程内部 SQL,需进包体查上下文
怎么验证这条高 CPU SQL 真正干了什么
AWR 报告里的 SQL 文本可能被截断(尤其带长 in-list 或动态拼接的),SQL Text 栏只显示前 1000 字符。直接用 SQL ID 去查 v$sql 或 dba_hist_sqltext:
SELECT sql_text FROM dba_hist_sqltext WHERE sql_id = 'abc123xyz';
更关键的是看它的执行计划是否稳定:v$sql_plan 里同 SQL ID 可能对应多个 plan_hash_value。如果报告里这条 SQL 的 Plan Hash Value 在近期频繁变化,说明执行计划抖动,不是 SQL 写法问题,而是绑定变量窥探、统计信息过期或自适应计划切换导致的。
- 用
dba_hist_sqlstat查它最近 7 天的elapsed_time_delta / executions_delta趋势,确认是不是突然变慢 - 对比
buffer_gets_delta / executions_delta,如果逻辑读暴增但 CPU 也涨,大概率是走了全表扫描或嵌套循环没走索引 - 如果
disk_reads_delta很低但 CPU 高,基本排除 I/O 问题,聚焦算法、函数索引、大量 PL/SQL 调用或隐式类型转换
为什么有些高 CPU SQL 在 v$session 里找不到活跃会话
AWR 是采样聚合数据,SQL ordered by CPU Time 统计的是快照周期内所有执行该 SQL 的会话累计 CPU 时间。它不保证此刻正在跑——可能刚执行完,也可能已结束。
想抓实时现场,不能只等 AWR 报告生成后翻,得同步做:
- 在问题时间段内,每 5 秒执行一次:
SELECT sql_id, sql_exec_start, program, event FROM v$session WHERE status = 'ACTIVE' AND sql_id IS NOT NULL; - 结合
v$active_session_history(ASH)查过去一小时的高频堆栈:SELECT sql_id, COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/24 GROUP BY sql_id ORDER BY 2 DESC; - 注意:ASH 默认保留 1 小时,且依赖
Diagnostic Pack授权;没授权的话,v$session+top -Hp+oradebug是唯一直接手段
常见误判点:DB CPU 高 ≠ 这条 SQL 该优化
看到 Top 5 Timed Events 第一是 CPU time,就冲进 SQL ordered by CPU Time 一顿优化,容易白忙活。真实场景中,高 CPU 往往是结果,不是根因:
- 如果
Hard Parses高(Load Profile 里看),可能是应用没绑定变量,千条相似 SQL 各自硬解析,CPU 被 Oracle 自身解析器吃掉,优化单条 SQL 没用 - 如果
Recursive Calls占比超 40%,说明大量触发触发器、物化视图刷新或 DBMS_STATS 自动收集,得查v$sysstat里的recursive calls和execute count比值 - RAC 环境下
gc cr block busy高,也会让 CPU 上升——进程在等跨节点块传输,表面看是 CPU,实际是私网或缓存融合问题
AWR 报告里没有“为什么 CPU 高”的答案,只有“谁在用 CPU”。真正定位根因,得把 SQL ordered by CPU Time 当作线索,再回溯到等待事件、解析行为、集群状态这些上下文里交叉验证。漏掉任一环,优化就可能打偏。


















