直接查v$sysaux_occupants可秒级定位SM/OPTSTAT是否导致SYSAUX空间膨胀,执行SELECT occupant_name,ROUND(space_usage_kbytes/1024/1024,2)AS gb FROM v$sysaux_occupants WHERE occupant_name LIKE 'SM/OPTSTAT%' ORDER BY space_usage_kbytes DESC;若返回值>1GB(尤其>5GB)即可锁定问题源。

直接查 v$sysaux_occupants,别翻 dba_segments —— 它能秒级定位是不是 SM/OPTSTAT 在吃空间。
用 v$sysaux_occupants 快速确认是否是 OPTSTAT 膨胀
这个视图专为 SYSAUX “住户”设计,比扫描全库段快得多,也更准确:
- 执行
SELECT occupant_name, ROUND(space_usage_kbytes/1024/1024, 2) AS gb FROM v$sysaux_occupants WHERE occupant_name LIKE 'SM/OPTSTAT%' ORDER BY space_usage_kbytes DESC; - 如果返回值 > 1 GB(尤其 > 5 GB),基本可锁定问题源;
SM/OPTSTAT占比高但SM/ADVISOR或AUDSYS更高,则要换方向排查 - 注意:该视图在 19c 中始终可用,无需额外权限,且结果不含缓存延迟
查清统计信息保留策略和实际可用范围
dbms_stats.get_stats_history_retention 返回的是“设了多少”,但真正影响空间的是历史数据是否被 purge、以及 purge 后有没有 shrink —— 很多人卡在这一步:
- 运行
SELECT dbms_stats.get_stats_history_retention FROM dual;看当前保留天数(默认 31,19c 可设为 1~365) - 运行
SELECT dbms_stats.get_stats_history_availability FROM dual;查最早还能访问的统计时间点;若它比SYSDATE - get_stats_history_retention晚很多,说明 purge 任务没跑或失败了 - 常见坑:设置了 retention=7,但
get_stats_history_availability显示的是 30 天前——说明 purge 没生效,不是参数没生效,而是 purge 本身没触发或被阻塞
检查 WRI$_OPTSTAT 系列表真实占用和锁状态
即使确认是 OPTSTAT 膨胀,也不能直接删表;必须看具体哪几张表撑得最狠,以及它们是否支持在线 shrink:
- 查膨胀主表:
SELECT segment_name, bytes/1024/1024/1024 gb FROM dba_segments WHERE owner='SYS' AND segment_name LIKE 'WRI$_OPTSTAT%' AND tablespace_name='SYSAUX' ORDER BY bytes DESC; - 重点关注:
wri$_optstat_tab_history(表级)、wri$_optstat_ind_history(索引级)、wri$_optstat_histgrm_history(直方图级) - 关键限制:这些系统表默认
ROW MOVEMENT是禁用的,ALTER TABLE ... SHRINK SPACE会报ORA-10631;必须先ENABLE ROW MOVEMENT才能 shrink - 操作期间表会被短暂加锁,避开 AWR 快照生成窗口(通常是凌晨 2–4 点)和业务高峰
别漏掉统计信息顾问(AUTO_STATS_ADVISOR_TASK)这个隐藏大户
12.2+ 版本起,AUTO_STATS_ADVISOR_TASK 会把分析结果写进 WRI$_ADV_OBJECTS,它不属于 SM/OPTSTAT,但在 v$sysaux_occupants 里归在 SM/ADVISOR 下——容易误判为“跟 OPTSTAT 无关”:
- 查任务调用频次:
SELECT task_name, COUNT(*) cnt FROM dba_advisor_objects GROUP BY task_name ORDER BY cnt DESC;,若AUTO_STATS_ADVISOR_TASK排第一且数量超 10 万,就是它 - 清理方式不同:
EXEC dbms_stats.drop_advisor_task('AUTO_STATS_ADVISOR_TASK');—— 这会连带清空WRI$_ADV_OBJECTS及其索引 - 清完必须
ALTER TABLE sys.wri$_adv_objects MOVE;+ALTER INDEX ... REBUILD;,否则空间不释放
真正难处理的不是“怎么删”,而是删完后空间不回收——purge_stats 只删行,SHRINK SPACE 才降高水位,而后者又依赖 ENABLE ROW MOVEMENT。三个动作缺一不可,顺序不能错,否则白忙活。


















