不能只看executions最高的sql,因其不反映单次耗时与资源消耗;高频慢sql需同时满足执行频次高、单次耗时≥0.3秒、ash显示真实数据库等待。

直接看 SQL ordered by Executions 列表没用——执行次数多不等于慢,必须叠加单次耗时阈值和资源消耗特征才能筛出真正要优化的“高频慢SQL”。
为什么不能只看 Executions 最高的 SQL
AWR 报告中 SQL ordered by Executions 仅按总执行次数排序,完全不反映单次性能。一条每秒执行 500 次、每次仅 2ms 的语句,总耗时可能远超一条每小时执行 1 次、但单次耗时 8 秒的语句。盲目优化前者,对用户体验几乎无感;漏掉后者,则可能正是接口超时的根因。
-
Executions高但Elapsed Time per Exec (s) -
Executions中等(50–500),但Elapsed Time per Exec (s)> 0.5 → 需优先关注:高频 + 单次已明显拖慢响应 -
Executions低(Buffer Gets per Exec > 100000 → 可能是隐式全表扫描或嵌套循环失控,即使执行少也得查
筛选“高频慢SQL”的三步交叉验证法
仅靠报告页面无法下结论,需结合指标组合、文本特征与基表下钻:
- 在 AWR 报告中定位
SQL ordered by Executions页面,筛选满足以下任一条件的前 10 条:Executions >= 50且Elapsed Time per Exec (s) >= 0.3;或Executions >= 10且CPU Time per Exec (s) >= 0.2 - 复制对应
sql_id,查v$sql确认当前是否仍在共享池:SELECT sql_text, executions, elapsed_time/executions/1000000 avg_sec FROM v$sql WHERE sql_id = 'xxx';若executions为 0 或为空,说明该语句已被老化出内存,需转查dba_hist_sqlstat - 用
DBA_HIST_SQLSTAT补全历史趋势:SELECT snap_id, executions_delta, elapsed_time_delta/1000000 elap_sec, buffer_gets_delta FROM dba_hist_sqlstat WHERE sql_id = 'xxx' AND snap_id BETWEEN &begin_snap AND &end_snap ORDER BY snap_id;重点看是否在多个快照中持续高执行+高单次耗时
容易被忽略的伪高频慢SQL陷阱
很多看似“执行多又慢”的 SQL,真实瓶颈不在逻辑本身:
-
parse_calls接近executions(比值 > 0.7)→ 实际是硬解析风暴,不是 SQL 慢,而是绑定变量缺失或cursor_sharing配置不当 -
SQL*Net message from client在 ASH 中占比突增 → 应用层调用间隔极短(如轮询),SQL 本身很快,但网络往返堆积了 wall-clock 时间 -
log file sync平均等待 > 5ms 且Executions高 → 事务粒度太小(如每条 UPDATE 都 COMMIT),优化方向是批量提交,而非改写 SQL - SQL 文本含
SELECT * FROM v$session或DBMS_LOCK.SLEEP→ DBA 工具类语句,不应出现在业务 AWR 统计中,需确认是否被误注入或监控脚本失控
真正要动手优化的“高频慢SQL”,必须同时满足:执行频次显著高于基线、单次耗时跨过 0.3 秒阈值、且 ASH 显示主要时间花在 db file sequential read、latch: cache buffers chains 或真实 CPU 运算上——缺一不可。否则你优化的可能根本不是用户抱怨的那个“慢”。











