sysaux表空间膨胀主因是wri$_optstat_历史统计表长期滞留且默认保留31天,需先调低保留期、手动purge_stats,再对相关表执行shrink space cascade释放空间。
sysaux表空间因统计信息过快增长,根本原因不是“收集太多”,而是历史统计信息长期滞留未清理——wri$_optstat_开头的表(如wri$_optstat_histhead_history、wri$_optstat_histgrm_history)持续累积,且默认保留策略宽松(31天),在频繁收集或大对象库中极易撑爆空间。
查确认是不是统计信息在吃空间
别猜,直接看占用排名:
- 运行
SELECT occupant_name, ROUND(space_usage_kbytes/1024/1024, 2) AS gb FROM v$sysaux_occupants WHERE space_usage_kbytes > 0 ORDER BY space_usage_kbytes DESC;—— 若OPTIMIZER或SM/OPTSTAT排前三,基本坐实 - 再查具体段:
SELECT segment_name, owner, segment_type, bytes/1024/1024/1024 AS gb FROM dba_segments WHERE tablespace_name = 'SYSAUX' AND segment_name LIKE 'WRI$_OPTSTAT%' ORDER BY bytes DESC; - 注意:
WRI$_OPTSTAT_HISTGRM_HISTORY常占数GB,尤其当列数多、直方图频繁更新时
为什么自动清理没起作用
DBMS_STATS 默认保留31天历史,但以下情况会让清理失效:
-
dbms_stats.alter_stats_history_retention被设为较大值(如90),或从未调用过该过程 - 手动执行过
dbms_stats.purge_stats但没指定时间点,或传入了错误的before_timestamp - 数据库版本存在已知 Bug(如 12.2.0.1 中某些 patch 缺失导致
purge_stats不触发物理删除) - 表上存在大量 LOB 列(如直方图数据存于
WRI$_OPTSTAT_HISTGRM_HISTORY的ENDPOINT_ACTUAL_VALUE),导致SHRINK SPACE失败或被跳过
清理时容易踩的坑
直接删表或 truncate 是高危操作,必须走 Oracle 官方路径:
- 先改保留期:
EXEC dbms_stats.alter_stats_history_retention(7);—— 建议设为 7~14 天,避免一刀切清空所有历史 - 再手动清理旧数据:
EXEC dbms_stats.purge_stats(SYSDATE - 10);—— 注意参数是时间点,不是天数 - 清理后空间不释放?正常。需对大表逐个收缩:
ALTER TABLE wri$_optstat_histhead_history SHRINK SPACE CASCADE;(前提:已ENABLE ROW MOVEMENT) - 禁用
ENABLE_PLSQL_DEBUG类调试功能,它们会额外写入WRI$_OPTSTAT相关跟踪数据
长期防复发的关键点
统计信息膨胀本质是“策略+监控”缺一不可:
- 每季度检查一次
dbms_stats.get_stats_history_availability返回值,确认是否真按设定天数保留 - 在
dba_tab_modifications高频变更表上,避免无差别全库收集;改用dbms_stats.lock_table_stats锁定稳定表 - 不要依赖
auto optimizer stats collection的默认窗口(通常凌晨),它可能和备份、ETL 冲突导致积压 -
WRI$_OPTSTAT表本身不支持分区,无法像 AWR 那样直接TRUNCATE PARTITION—— 这是它比WRH$系列表更难清理的根本限制
最常被忽略的是:统计信息历史清理不等于“删数据”,而是“标记可回收 + 主动收缩”,中间那步 SHRINK SPACE 没做,空间就永远卡在那里。











