AWR报告找不到慢SQL主因有三:SQL执行频次低于TOPNSQL阈值被过滤;未在共享池驻留足够时间致未被捕获;STATISTICS_LEVEL=BASIC或CONTROL_MANAGEMENT_PACK_ACCESS=NONE导致采集关闭。

AWR报告里找不到某些你确认很慢的SQL,不是它“漏报”了,而是根本没进AWR的采集视野——原因基本就三类:SQL没执行够次数、共享池里没留够时间、或者被参数或权限直接拦在门外。
SQL执行次数低于AWR默认阈值
AWR不会记录所有SQL,只抓“Top N”高频或高消耗的。11g默认只保留TOPNSQL个SQL(通常为30或50),按buffer_gets、disk_reads、cpu_time等指标排序。低频但单次极慢的SQL(比如每小时跑一次、但耗时60秒的报表)很容易被挤掉。
- 查当前设置:
SELECT * FROM dba_hist_wr_control;看TOPNSQL字段值 - 临时调高(需DBA权限):
EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(topnsql => 100); - 注意:调高后不回溯历史,只影响后续快照;且可能加重SYSAUX空间压力
v$sql中存在但DBA_HIST_SQLSTAT里查不到
AWR从v$sql采样数据,但不是所有v$sql里的语句都会落到DBA_HIST_SQLSTAT。常见断点:
- SQL刚执行完就被老化出共享池(
child_number高、loads低、invalidations多) -
_cursor_plan_unload_time隐含参数设得太小(默认3600秒),导致计划未满一小时就被清出 - SQL_ID被
DBMS_SHARED_POOL.PURGE手动踢出过,或触发了游标失效(如DDL、统计信息变更) - 检查是否真在历史视图里:
SELECT COUNT(*) FROM dba_hist_sqlstat WHERE sql_id = 'xxx';返回0就说明没被捕获
STATISTICS_LEVEL或CONTROL_MANAGEMENT_PACK_ACCESS限制采集
即使SQL执行频繁,若底层采集开关被关,AWR连元数据都不会存——这不是“没抓到”,是“压根没启动”。11g里最隐蔽的坑在这两个参数上:
-
STATISTICS_LEVEL = BASIC:AWR快照仍生成,但DBA_HIST_SQLSTAT全为空值,v$sql里executions、elapsed_time等字段也归零 -
CONTROL_MANAGEMENT_PACK_ACCESS = NONE:11.1–11.2经典问题,快照有ID、有时间戳,但所有性能字段(包括SQL执行统计)全为NULL,DBA_HIST_SQLSTAT表存在但无有效数据 - 验证命令:
SELECT name, value FROM v$parameter WHERE name IN ('statistics_level', 'control_management_pack_access');
真正难排查的是第三种情况:表面一切正常(STATISTICS_LEVEL=TYPICAL,快照ID连续,DBA_HIST_SNAPSHOT有数据),但DBA_HIST_SQLSTAT就是空——这时候必须立刻查control_management_pack_access,而不是继续翻SQL文本或调大shared_pool。


















