先用v$sysaux_occupants确认sm/optstat实际占用gb数,再查dbms_stats.get_stats_history_retention和get_stats_history_availability;若保留期远超需求,执行purge_stats清理数据,再对wri$_optstat系列表依次启用行移动并shrink space cascade释放物理空间。

查清楚WRI$_OPTSTAT相关表到底占了多少空间
别一上来就删,先确认是不是真由它撑大了SYSAUX。v$sysaux_occupants视图比dba_segments更准、更快,直接暴露功能模块级占用:
- 执行:
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; - 若返回
SM/OPTSTAT占几GB甚至十几GB,且GET_STATS_HISTORY_RETENTION远高于业务需要(比如设成365但实际只查近7天),那基本就是它了 - 顺手查下保留策略:
SELECT dbms_stats.get_stats_history_retention FROM dual;和可用最早时间:SELECT dbms_stats.get_stats_history_availability FROM dual;
用purge_stats清理历史,但别指望立刻释放磁盘空间
dbms_stats.purge_stats只删数据行,不降高水位(HWM),表段物理空间不会自动回收——这是最常被忽略的点:
- 安全清理示例(保留最近10天):
EXEC dbms_stats.purge_stats(SYSDATE - 10); - 执行后立即查
dba_segments,你会发现WRI$_OPTSTAT_TAB_HISTORY等表的bytes几乎不变 - 原因:Oracle 19c默认不自动shrink系统表;必须手动触发收缩,否则空间一直被“虚占”
对WRI$_OPTSTAT系列表执行SHRINK SPACE
系统表默认禁用ROW MOVEMENT,直接SHRINK SPACE会报ORA-10631,得先开再缩:
- 启用行移动:
ALTER TABLE sys.wri$_optstat_tab_history ENABLE ROW MOVEMENT; - 收缩表+索引:
ALTER TABLE sys.wri$_optstat_tab_history SHRINK SPACE CASCADE; - 同理处理其他膨胀表:
wri$_optstat_ind_history、wri$_optstat_histhead_history、wri$_optstat_histgrm_history - 注意:操作期间表会被短暂加锁,避开业务高峰;19c中这些操作在线可行,但别在AWR快照生成窗口内做
避免下次又爆满:关掉统计信息自动保留或调低阈值
默认31天保留期在高频收集场景下极易失控,尤其搭配自动任务(如GATHER_STATS_JOB)时:
- 永久调低(推荐):
EXEC dbms_stats.alter_stats_history_retention(7); - 验证生效:
SELECT dbms_stats.get_stats_history_retention FROM dual;必须看到7 - 额外保险:检查是否有残留的统计信息收集作业干扰,查
dba_scheduler_jobs里状态为ENABLED的gather%类任务 - 切记:不要用
DELETE FROM sys.wri$_optstat_*——字典表直接DML风险极高,ORA-600概率陡增
真实清理效果取决于两步是否都做完:先purge_stats删数据,再SHRINK SPACE收空间。漏掉第二步,SYSAUX使用率数字根本不会动。











