Oracle 19c 不支持 ALTER INDEX ... SHRINK SPACE,语法报错 ORA-00905;正确方式是 ALTER INDEX ... REBUILD ONLINE,并注意表空间、并行度、NOLOGGING 及 ORPHANED_ENTRIES 清理。

Oracle 19c 不支持 shrink space 直接收缩索引段
直接说结论:ALTER INDEX ... SHRINK SPACE 在 Oracle 19c 中**语法不被识别**,执行会报错 ORA-00905: missing keyword。这是因为索引段(INDEX segment)本身不支持 SHRINK 操作——该命令仅对堆表(heap table)及其分区有效。很多 DBA 误以为和表一样能 shrink,结果卡在第一步。
ALTER INDEX ... REBUILD ONLINE 是实际可行的在线收缩方式
重建索引才是释放索引碎片、降低高水位线(HWM)、回收空间的正确路径。关键在于用好 ONLINE 和空间参数组合:
-
ONLINE:避免阻塞 DML,但需注意它仍会产生大量 redo 和临时段,业务高峰期慎用 -
NOPARALLEL或显式设低并行度(如PARELLEL 2):避免争抢 CPU 和 temp 空间,尤其在资源紧张时 -
TABLESPACE指定目标表空间:可借此把索引从拥挤的E3_DATA迁到空闲的E3_INDX,间接“腾出”原表空间 -
NOLOGGING(仅限归档关闭或可接受丢失的场景):大幅减少 redo 生成,但必须确保备份策略覆盖该风险
示例命令:
ALTER INDEX idx_emp_email REBUILD ONLINE TABLESPACE E3_INDX PARALLEL 2;
执行后立即生效,索引状态保持 VALID,查询不受影响。
分区索引需额外处理 ORPHANED_ENTRIES
如果索引是全局索引(global index),且其基表是分区表,并曾执行过 DROP PARTITION ... UPDATE GLOBAL INDEXES,那么索引可能处于 ORPHANED_ENTRIES = 'YES' 状态——此时单纯 REBUILD 不能清除游离条目,空间不会真正释放。
必须先确认状态:
SELECT INDEX_NAME, STATUS, ORPHANED_ENTRIES FROM DBA_INDEXES WHERE TABLE_NAME = 'T_TEST';
若 ORPHANED_ENTRIES 为 YES,需手动触发清理:
- 调用
DBMS_PART.CLEANUP_GIDX('OWNER', 'TABLE_NAME') - 或立即运行维护任务:
EXEC DBMS_SCHEDULER.RUN_JOB('PMO_DEFERRED_GIDX_MAINT_JOB') - 再执行
REBUILD才能彻底收缩
收缩前务必检查空间与权限
容易被跳过的两个硬性前提:
- 目标表空间必须有足够空闲空间容纳重建过程中的新索引副本(通常需原大小 1.2–1.5 倍);查
DBA_FREE_SPACE比只看DBA_SEGMENTS更可靠 - 用户需具备
ALTER ANY INDEX(跨 schema)或对象级ALTER权限;在多租户环境(CDB/PDB)中,还必须确认当前容器是目标 PDB,否则操作静默失败
最常被忽略的一点:REBUILD 后旧索引段不会立刻删除,而是等延迟清理(deferred segment drop)触发,中间存在几秒到几分钟的“双副本”窗口——监控 DBA_SEGMENTS 时会看到两个同名索引段短暂共存。


















