cpu per sec 不是 awr 原生指标,真正需关注 cpu per exec、executions per sec 和 os 层 busy_time/(busy_time+idle_time) 三者组合;单独计算“每秒cpu秒数”会掩盖突发性、忽略并发与os干扰,导致误判。

CPU Per Sec 不是 AWR 原生指标,它属于误读或人工计算产物——直接查这个值会跑偏,真正该盯的是 CPU per Exec、Executions per Sec 和底层 OS 的 BUSY_TIME/(BUSY_TIME+IDLE_TIME) 比例。
为什么“CPU Per Sec”在AWR里根本不存在
AWR 报告中没有名为 CPU Per Sec 的统计项。有人从 “SQL ordered by CPU Time” 表格里用总 CPU_TIME_SEC 除以快照时长(如 3600 秒)手动算出一个“每秒 CPU 秒数”,但这严重失真:
- 它把所有 SQL 的 CPU 消耗平摊到整段快照,掩盖了突发性、周期性或单点毛刺
- 忽略并发会话数:1 个会话占满 12 核 1 秒,和 12 个会话各占 1 核 1 秒,算出来都是 12,但系统压力完全不同
- 混淆 DB CPU 和 OS CPU:DB CPU 是 Oracle 进程累计值,可能远超物理核数(比如 12 核机器报告 60 秒 DB CPU,说明平均 5 核持续满载),但它不反映其他进程(如备份、监控 agent)是否也在抢 CPU
真正该查的三个核心指标组合
定位 CPU 异常飙升,必须同时看这三项,缺一不可:
-
CPU per Exec:在 “SQL ordered by CPU Time” 表格里,列名是CPU per Exec (s)。跳过EXECUTIONS = 0但CPU_TIME_SEC > 0的干扰项;重点关注CPU per Exec > 5且Executions per Sec > 0.1的 SQL —— 它们才是稳定输出 CPU 压力的“定时炸弹” -
Executions per Sec:同一行里就有该值。若某 SQL 每秒执行 20 次、每次耗 0.3 秒 CPU,实际每秒吃掉 6 秒 CPU 时间,比单次耗 8 秒但每分钟才执行 1 次的语句危害更大 -
BUSY_TIME/(BUSY_TIME+IDLE_TIME):去 AWR 的 “Operating System Statistics” 部分,手动计算这个比例。数值大(如 92%)不代表真忙——得结合IOWAIT_TIME和LOAD看:若IOWAIT_TIME占比突增、LOAD持续 > CPU 核数,大概率是磁盘卡住导致 CPU 在等,不是计算密集型问题
当 CPU per Exec 突增时,优先检查 plan_hash_value 是否漂移
同一 sql_id 的 CPU per Exec 在两个快照间翻倍以上?别急着优化 SQL 文本,先确认执行计划有没有变:
- 执行
SELECT sql_id, plan_hash_value, executions, ROUND(elapsed_time / NULLIF(executions, 0)) cpu_per_exec FROM dba_hist_sqlstat WHERE sql_id = '<your_sql_id>' ORDER BY snap_id</your_sql_id>,观察plan_hash_value是否突变 - 若变了,立刻用
DBMS_XPLAN.DISPLAY_AWR('<sql_id>')</sql_id>查两份计划,重点对比是否出现TABLE ACCESS FULL、NESTED LOOPS驱动大表、或FILTER操作被推到外层循环 - 注意:AWR 报告只列 Top 30 SQL,且不标记
plan_hash_value变化。很多 CPU 飙升源于计划从 12345 变成 67890,但报告里根本看不出
硬解析失控时,“Top SQL” 里往往一条都看不到
如果 CPU per Exec 都不高,但 DB CPU 占 DB Time 超过 70%,且 Parse CPU to Parse Elapsd % 低于 20%,就要怀疑硬解析:
- 查
Instance Efficiency Percentages区域的Execute to Parse %:持续低于 40% +parse count (hard) / parse count (total) > 10%,基本坐实 - 查
v$sql找未绑定变量的源头:SELECT force_matching_signature, exact_matching_signature, COUNT(*) FROM v$sql WHERE last_load_time >= TO_DATE('2026-09-17 18:00', 'YYYY-MM-DD HH24:MI') GROUP BY force_matching_signature, exact_matching_signature HAVING COUNT(*) > 20 AND force_matching_signature != exact_matching_signature - 别碰
cursor_sharing=force:它会绕过 12c+ 的自适应游标共享(ACS),引发执行计划泛滥和library cache lock加剧;真正该做的是让应用把WHERE status = 1改成WHERE status = :b1
最易被忽略的一点:AWR 快照是离散的,CPU 波峰常落在两个快照中间。单看一份报告容易漏掉瞬时毛刺,必须用 dba_hist_snapshot 精确确认问题时段是否存在快照,再决定是补采快照、查 ASH,还是直接抓实时 v$session 和 v$process。











