sql执行次数暴增是应用逻辑异常或调度失控的信号,需用awr通过dba_hist_snapshot定位时段,再以executions_delta计算真实增幅,并结合执行计划、等待事件等线索识别定时作业、重试失控、硬解析或循环调用等根因。

SQL执行次数暴增不是性能瓶颈本身,而是应用逻辑异常或调度失控的明确信号——AWR能帮你快速确认它是否真实发生、发生在哪个时段、由哪条SQL引发,并排除采样误差干扰。
怎么看执行次数是否真暴增?别只信Top SQL页面的Executions总数
AWR报告里“SQL ordered by Executions”页面显示的是快照区间内累计执行次数,但这个数字容易误判:
- 同一SQL_ID在不同快照中PLAN_HASH_VALUE变化时,
DBA_HIST_SQLSTAT会拆成多行记录,总和可能被重复计算 - 快照时间窗口选得不准(比如跨了两个业务高峰),数值天然偏高
-
EXECUTIONS_TOTAL字段为0时,某些版本Oracle仍参与排序,导致无效SQL排在前列
正确做法是:先查DBA_HIST_SNAPSHOT确认问题时段对应的begin_snap和end_snap,再用以下SQL算单条SQL的真实增幅:
SELECT sql_id,
SUM(executions_delta) AS exec_count,
ROUND(SUM(elapsed_time_delta)/1000000, 2) AS sec_total
FROM dba_hist_sqlstat
WHERE snap_id BETWEEN <code>begin_snap</code> AND <code>end_snap</code>
AND executions_delta > 0
GROUP BY sql_id
ORDER BY exec_count DESC FETCH FIRST 10 ROWS ONLY;
注意必须用executions_delta而非executions_total,后者是累积值,跨快照不可比。
执行次数突增常见原因及对应AWR线索
不是所有高频执行都代表有问题。关键看它是否违背业务预期:
- 定时作业类:如每小时刷新物化视图,
DBA_SCHEDULER_JOB_RUN_DETAILS中job_name含REFRESH,且actual_start_date集中在整点附近 - 应用重试逻辑失控:某SQL在
Top 5 Timed Events中enq: TX - row lock contention或log file sync占比突增,说明事务反复失败重试 - 绑定变量未生效:同一
SQL_ID下PLAN_HASH_VALUE不变,但DBA_HIST_SQLSTAT.CPU_TIME_DELTA与ELAPSED_TIME_DELTA比值大幅下降,大概率走了硬解析+全表扫描 - 循环调用未节流:该SQL的
Buffer Gets per Exec极低(Executions高达数万,典型如“查单条配置”的接口被前端轮询轰炸
怎么确认是不是同一条SQL在反复执行?重点看这三个字段
仅靠SQL_ID不够。Oracle对文本稍作空格/大小写调整就会生成新SQL_ID,而真正语义相同的SQL可能分散在多个ID下:
- 查
v$sql中sql_text前200字符是否高度相似(用DBMS_LOB.SUBSTR截取) - 对比
DBA_HIST_SQLSTAT中相同sql_id的hash_value和old_hash_value,二者一致才说明执行计划结构未变 - 运行
DBMS_XPLAN.DISPLAY_AWR('<code>SQL_ID'),检查Predicate Information段落里的过滤条件是否完全一致——尤其注意日期函数如TRUNC(SYSDATE)vsSYSDATE-1
如果发现多个SQL_ID执行同一张表、走同样索引、WHERE条件仅参数不同,基本可断定是应用层未启用绑定变量。
执行次数暴增后下一步必须做的三件事
定位到SQL只是开始,不验证就优化等于蒙眼调参:
- 立刻查
DBA_HIST_ACTIVE_SESS_HISTORY,用sql_id+sample_time范围过滤,确认是否真有大量会话同时执行——避免把ASH采样抖动当真实并发 - 用
DBMS_XPLAN.DISPLAY_AWR('<code>SQL_ID', NULL, 'ADVANCED')看PEEKED_BINDS部分,确认当前绑定值是否触发了统计信息偏差(例如直方图缺失导致基数估算错误) - 核对
DBA_TAB_MODIFICATIONS中对应表的INSERTS/UPDATES数量,如果远高于该SQL的EXECUTIONS,说明还有其他源头在改数据,执行次数暴增只是表象
真正难处理的,往往是那些执行次数翻了10倍但单次耗时反而下降的SQL——它没拖慢数据库,却可能把应用服务器CPU打满,这种问题AWR看不到,得去应用日志里捞调用链。











