Segment Advisor仅提建议不执行清理,需人工执行SHRINK SPACE并重建索引,或结合DBMS_SCHEDULER编写定时PL/SQL脚本实现周期性空间回收。

Oracle 的 Segment Advisor 本身不执行清理,只提建议;想靠它“定期清理”,必须搭配人工执行收缩或手动调度任务,否则空间永远不会释放。
Segment Advisor 的建议不会自动变成 SHRINK 操作
Automatic Segment Advisor 默认每晚在维护窗口运行,扫描 HWM 上方空闲空间占比 > 10% 的段,并把结果写入 DBA_ADVISOR_FINDINGS。但它绝不会触发 ALTER TABLE ... SHRINK SPACE,也不会删数据、截断表或移动段。
- 它输出的是文本建议,比如 “Consider shrinking this table” —— 这不是命令,是提醒
- 真正释放空间必须人工执行:
ALTER TABLE sales SHRINK SPACE COMPACT - 若表未启用
ROW MOVEMENT,SHRINK 直接报错ORA-10636 - 索引不会随 SHRINK 自动更新,必须单独重建:
ALTER INDEX sales_idx REBUILD
想“定期”执行,得自己写 PL/SQL + DBMS_SCHEDULER
Oracle 没有内置的“自动 SHRINK 调度器”。要让空间回收形成周期性动作,需组合以下三步:
- 用
DBMS_ADVISOR.TUNE_SEGMENT或查询DBA_ADVISOR_FINDINGS找出待处理段 - 写 PL/SQL 块:对每个候选段检查
ROW MOVEMENT状态、执行SHRINK、捕获ORA-10636等错误并跳过 - 用
DBMS_SCHEDULER.CREATE_JOB创建定时 JOB,例如每天凌晨 1:30 运行
示例关键逻辑片段:
DECLARE
CURSOR c_segments IS
SELECT owner, segment_name, segment_type
FROM DBA_ADVISOR_FINDINGS f, DBA_SEGMENTS s
WHERE f.object_id = s.header_file || ',' || s.header_block
AND f.task_name = 'AUTO_SEGADV_TASK'
AND f.impact > 20;
BEGIN
FOR r IN c_segments LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER ' || r.segment_type || ' ' ||
r.owner || '.' || r.segment_name ||
' SHRINK SPACE COMPACT';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -10636 THEN
EXECUTE IMMEDIATE 'ALTER ' || r.segment_type || ' ' ||
r.owner || '.' || r.segment_name ||
' ENABLE ROW MOVEMENT';
EXECUTE IMMEDIATE 'ALTER ' || r.segment_type || ' ' ||
r.owner || '.' || r.segment_name ||
' SHRINK SPACE COMPACT';
END IF;
END;
END LOOP;
END;
别被 SYSAUX 里 SM/ADVISOR 占用吓到
查 V$SYSAUX_OCCUPANTS 发现 SM/ADVISOR 占了 8GB,这不是临时段泄漏,而是 WRI$_ADV_OBJECTS 表中堆积的历史建议元数据。它不会被 SMON 清理,也不影响业务性能,但会持续增长。
- 确认是否真由 Segment Advisor 主导:
SELECT task_name, COUNT(*) FROM dba_advisor_objects GROUP BY task_name ORDER BY 2 DESC - 停用自动任务:
DBMS_AUTO_TASK_ADMIN.DISABLE('auto optimizer stats collection', NULL, NULL)(注意:这会同时关掉统计信息收集) - 清历史数据必须手动:
ALTER TABLE WRI$_ADV_OBJECTS MOVE+ALTER INDEX ... REBUILD,DROP_ADVISOR_TASK不释放空间
真正卡住空间回收的,往往不是 Advisor 本身,而是没开 ROW MOVEMENT、忘了重建索引、或者误以为 DBA_SEGMENTS 能反映临时段真实占用——这些细节不验证,定期脚本跑十次也白搭。


















