AWR的topnsql参数控制每快照捕获的Top SQL数量,默认30,需用DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS修改,范围1–100,仅影响后续快照。
AWR快照里SQL数量太少,topnsql参数在哪改
awr默认只保留每个快照中执行时间最长的30条sql(topnsql=30),想看更多,得改这个参数。它不是在init.ora或spfile里配的,而是存在数据字典里,用dbms_workload_repository包修改。
-
topnsql是AWR内部控制每份快照捕获多少条“Top SQL”的阈值,影响DBA_HIST_SQLSTAT和DBA_HIST_SQLTEXT里能查到的SQL数量 - 修改必须用
sys或具有ADMINISTER DATABASE TRIGGER权限的用户执行 - 改完不会立即生效,只对后续新生成的快照起作用;已有快照里的SQL数量不会回填
- 可设范围是1–100,超过100会报错
ORA-13541: topnsql value must be between 1 and 100
示例:把TOP SQL数量提到60
EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(topnsql => 60);
改了topnsql但快照里还是没多出SQL
常见误解是“改完就能看到历史快照变多”,其实AWR不会重算旧快照。另外,即使设成100,也不代表每份快照真有100条SQL入库——它只取“该快照周期内排序前N的SQL”,如果某次采样周期内活跃SQL本身就少,或者大量SQL执行时间/逻辑读非常接近,可能仍不足设定值。
- 检查当前设置是否生效:
SELECT topnsql FROM dba_hist_wr_control; - 确认快照时间窗口内是否有足够“差异化”的高负载SQL;比如全是短平快的OLTP语句,
elapsed_time拉不开差距,就容易被截断 - 注意
topnsql只影响按执行时间排序的SQL;不控制按CPU、IO、buffer gets等维度排名的SQL数量(那些由其他隐含参数控制) - 如果应用大量使用绑定变量且SQL文本相同,
DBA_HIST_SQLTEXT里只会存一条,但DBA_HIST_SQLSTAT里仍按sql_id分开统计——别误以为“没多出来”
topnsql调太高有什么代价
增大topnsql直接增加每次快照采集时的内存开销和写入量,尤其在高并发、SQL种类多的系统上,可能拖慢快照生成速度,甚至导致AWR flush超时。
- 每多记1条SQL,就要多写几行到
WRH$_SQLSTAT基表,还涉及关联的WRH$_SQLTEXT、WRH$_SQL_BIND_METADATA等 - Oracle 12c+默认启用了
SQL Plan Directives和Auto SQL Tuning,这些功能也会读取同一套Top SQL数据,topnsql过大可能间接加重后台任务负担 - 实测中,从30调到60一般无感;但跳到100后,在峰值每秒数百SQL执行的库上,单次快照生成时间可能延长10%~20%
- 备份和传输AWR数据(如用
DBMS_SWRF_INTERNAL导出)体积也会线性增长
有没有比改topnsql更灵活的替代方案
硬调topnsql是全局开关,不够精准。真要深度分析某类SQL,不如绕过AWR快照限制,直接查实时或近实时数据源。
- 查
V$SQL或V$SQLAREA:能看到当前共享池里所有解析过的SQL,不受topnsql限制,但生命周期短,重启或刷库就丢 - 开启SQL Trace +
DBMS_MONITOR:对特定模块/用户/服务做定向捕获,比AWR粒度细、无上限,只是需要提前规划 - 用
ASH(V$ACTIVE_SESSION_HISTORY)反推:虽然ASH本身也不存完整SQL文本,但结合sql_id去V$SQLTEXT捞,能还原出当时正在跑的任意SQL - 12c+可用
DBMS_AUTO_SQLTUNE的自定义任务,指定scope="COMPREHENSIVE"并扩大time_limit,它会主动扫描更多候选SQL
真正难的不是“怎么让AWR多记几条”,而是判断哪些SQL值得记——盲目调高topnsql,最后查出来的可能全是低价值的重复查询。留心那些没进Top但持续消耗CPU的短SQL,它们常被topnsql机制漏掉。

















