IOT不能SHRINK或在线重定义,因其物理结构为B+树索引段且数据与索引合一;Oracle内核层硬性禁止,报ORA-10638或CAN_REDEF_TABLE失败;唯一可靠路径是ALTER TABLE MOVE重建(含OVERFLOW显式处理)并重建二级索引。

Oracle 19c 中无法对索引组织表(IOT)执行 SHRINK SPACE 或在线重定义(DBMS_REDEFINITION),这是硬性限制——不是操作姿势不对,而是内核层直接禁止。所谓“聚集表段”,若指 IOT,则必须换路径处理。
为什么 IOT 不能 SHRINK 或在线重定义
IOT 的物理结构是按主键排序的 B+ 树索引段,数据和索引合并在同一结构中。Oracle 明确不支持对 IOT 执行以下操作:
-
ALTER TABLE ... SHRINK SPACE→ 直接报ORA-10638: Index Organized Table not supported for shrink -
DBMS_REDEFINITION.CAN_REDEF_TABLE→ 返回失败,因 IOT 不满足在线重定义前提条件(文档明确排除 IOT、堆外对象、SYS 拥有对象等) - 即使强行建中间表并调用
START_REDEF_TABLE,也会在验证阶段中断,不会进入同步流程
替代方案:重建 IOT(MOVE + REBUILD)是唯一可靠路径
必须接受“非在线”事实:重建期间表不可写,需安排维护窗口。关键不是避免锁,而是最小化停机与风险:
- 先确认 IOT 结构:
SELECT iot_type, iot_name FROM dba_tables WHERE table_name = 'YOUR_IOT'→ 必须为IOT或IOT_OVERFLOW - 备份依赖对象:IOT 的二级索引(
dba_indexes中index_type = 'IOT - TOP')、约束、触发器需记录并重建 - 执行重建:
ALTER TABLE t MOVE PCTFREE 5 OVERFLOW PCTFREE 5——OVERFLOW子句必须显式指定,否则溢出段不被压缩 - 重建所有二级索引:
ALTER INDEX idx_name REBUILD ONLINE(注意:IOT 主键索引随 MOVE 自动重建,但二级索引不会) - 重建后立即收集统计信息:
DBMS_STATS.GATHER_TABLE_STATS,否则优化器仍按旧 HWM 和 BLOCKS 估算
MOVE 前必须检查的三个隐藏陷阱
看似简单的一条 MOVE 命令,常因以下原因失败或白忙:
- 表空间不是 ASSM:IOT
MOVE要求所在表空间为自动段空间管理(SEGMENT_SPACE_MANAGEMENT = 'AUTO'),查dba_tablespaces确认;手工管理(MSSM)下 MOVE 会静默忽略PCTFREE设置 - 溢出段(overflow segment)未单独处理:若 IOT 含大字段(如
LOB或VARCHAR2(4000)),其溢出段独立存在,MOVE不自动收缩它;需额外执行:ALTER TABLE t MOVE OVERFLOW INCLUDING ROWID或针对溢出段名单独MOVE - 未禁用并行 DML:会话级若启用
ALTER SESSION ENABLE PARALLEL DML,IOT MOVE 可能报ORA-12838;执行前加ALTER SESSION DISABLE PARALLEL DML
重建后空间没降?重点盯 overflow segment 和索引段
执行完 MOVE,dba_segments.bytes 不变小,八成问题不在主 IOT 段本身:
- 查溢出段大小:
SELECT segment_name, bytes FROM dba_segments WHERE segment_name IN (SELECT overflow FROM dba_tables WHERE table_name = 'YOUR_IOT')—— 它可能比主段还大,且未被 MOVE 触及 - 查二级索引段:
SELECT index_name, bytes FROM dba_segments WHERE segment_name IN (SELECT index_name FROM dba_indexes WHERE table_name = 'YOUR_IOT' AND index_type != 'IOT - TOP')—— 这些索引未重建时仍指向旧块地址 - 临时段残留:MOVE 过程中若发生大量排序(如含
ORDER BY的物化视图刷新同时运行),可能占满 TEMP,导致 MOVE 中断并留下半成品段;查v$sort_usage确保无活跃临时段
真正释放空间的节点,是 MOVE 完成且所有相关段(主表、溢出段、二级索引)都重建完毕的那一刻——少一个,空块就还在磁盘上躺着。











