Segment Advisor未返回收缩建议是因为仅对满足条件的段(如启用ROW MOVEMENT、本地管理表空间、AUTO段空间管理、大小≥10MB等)且HWM下存在显著空闲空间时才生成SEGMENT_SHRINK建议。
Segment Advisor 为什么没返回收缩建议
segment advisor 默认只对满足特定条件的段(segment)生成自动收缩建议,不是所有表或索引都会触发。它不会主动建议 shrink,除非检测到显著的高水位线(hwm)以下空闲空间,且该段支持在线收缩(即启用了 row movement,且不是 iot、簇表、物化视图日志等受限对象)。
常见错误现象:DBMS_SPACE.ASA_RECOMMENDATIONS 返回空结果,或 DBA_ADVISOR_FINDINGS 中无类型为 SEGMENT_SHRINK 的记录。
- 确认段所在表空间是本地管理(
EXTENT MANAGEMENT LOCAL),且段空间管理为AUTO(非MANUAL) - 检查是否已启用行移动:
SELECT row_movement FROM dba_tables WHERE table_name = 'YOUR_TABLE';— 必须为ENABLED - 避免对含 LONG、LOB(未启用
ENABLE STORAGE IN ROW)、函数索引、域索引运行 Advisor - 确保段大小超过默认阈值(通常 ≥ 10MB),否则 Advisor 可能跳过评估
如何手动触发 Segment Advisor 并获取 shrink 建议
依赖 DBMS_ADVISOR 包执行,不能靠 OEM 界面“一键生成”就默认得到 shrink 操作语句 — 它只输出建议类型和目标对象,具体 shrink 命令需人工判断后执行。
使用场景:日常空间巡检、归档后清理大表、迁移前压缩段体积。
- 先创建任务:
DBMS_ADVISOR.CREATE_TASK(指定ADVISOR_NAME => 'Segment Advisor') - 设置目标:
DBMS_ADVISOR.SET_TASK_PARAMETER中设'SCHEMA' => 'SCOTT'或'OBJECT_TYPE' => 'TABLE'和'OBJECT_NAME' => 'EMP' - 执行:
DBMS_ADVISOR.EXECUTE_TASK,完成后查DBA_ADVISOR_FINDINGS,过滤RECOMMENDATION_TYPE = 'SEGMENT_SHRINK' - 注意:
DBA_ADVISOR_RECOMMENDATIONS中的MESSAGE字段会写明“shrink space compact”还是“shrink space”,后者才真正回收空间
shrink space compact vs shrink space:别混用
Segment Advisor 建议里的 “shrink space” 不等于你直接执行 ALTER TABLE ... SHRINK SPACE 就完事 — 它分两步,且行为差异直接影响业务可用性。
性能与兼容性影响:前者不移动 HWM,仅整理块内碎片,秒级完成;后者移动 HWM 并释放空间给表空间,需独占 DML 锁,可能阻塞写操作。
-
SHRINK SPACE COMPACT:适合在线高峰期先做,不释放空间但为后续真正 shrink 减少锁时间 -
SHRINK SPACE:必须在低峰期执行,且要求表上无未提交事务、无正在运行的 DML - 如果表有启用的主键/唯一约束且含函数索引,
SHRINK SPACE可能报错ORA-10636: row movement is not enabled,即使ROW MOVEMENT已开 — 此时要先禁用再启用约束
Advisor 建议不可直接当 SQL 执行
它的输出是诊断结论,不是可执行脚本。比如建议里写 “Perform segment shrink on table EMP”,你得自己决定用 COMPACT 还是完整 SHRINK SPACE,还要确认索引是否需要重建(UPDATE INDEXES 子句)。
容易踩的坑:直接复制建议文本去执行,结果语法报错或收缩失败。
- 完整命令应类似:
ALTER TABLE scott.emp SHRINK SPACE CASCADE;(CASCADE自动处理依赖索引) - 若用
COMPACT,之后必须跟一次无参数的SHRINK SPACE才能释放空间 — Advisor 不会提醒这点 - 分区表需对每个分区单独调用,Advisor 可能只建议父表名,但实际要拆到
ALTER TABLE t MODIFY PARTITION p1 SHRINK SPACE
最常被忽略的是 shrink 后的统计信息失效问题 — DBMS_STATS.GATHER_TABLE_STATS 得手动补上,否则执行计划可能劣化。










