直接重建索引到独立表空间是唯一可靠方式,move不适用于索引;必须用alter index ... rebuild online tablespace,且需验证目标表空间状态、空间容量及用户权限,并避开lob列、函数索引等不支持场景。

直接重建索引到独立表空间是唯一可靠方式,MOVE不适用于索引——它只对表和LOB段有效。
为什么不能用 ALTER INDEX ... MOVE TABLESPACE
Oracle 没有 MOVE 索引的语法,ALTER INDEX ... MOVE 是非法语句,会报 ORA-02149。索引迁移必须走 REBUILD 路径,本质是删除旧索引、在目标表空间建新索引。这决定了操作不可逆、需预留双倍空间、且必须处理锁与权限问题。
-
REBUILD会重写整个索引结构,不是简单元数据切换 - 未加
ONLINE会导致整表 DML 阻塞(锁表),生产环境必须加 - 标准版 Oracle 不支持
ONLINE,执行会直接报 ORA-00439
怎么生成安全有效的 REBUILD 语句
不能手动逐个写,容易漏 schema、拼错名字、忽略大小写。必须从 DBA_SEGMENTS 动态生成,并显式带上 OWNER:
SELECT 'ALTER INDEX ' || owner || '.' || segment_name || ' REBUILD ONLINE TABLESPACE E3_INDX;' FROM dba_segments WHERE segment_type = 'INDEX' AND tablespace_name = 'E3_DATA' AND bytes > 1024*1024*1024;
- 省略
owner会导致语句默认找当前用户,跨用户索引就建错位置甚至报 ORA-01435 - 条件里限定
tablespace_name = 'E3_DATA'是为了只动“错位大索引”,避免误伤本就在E3_INDX的索引 - 如果目标表空间
E3_INDX还没建好,这条语句本身不会报错,但后续执行时会失败退出
执行前必须验证的三件事
90% 的重建失败都卡在这三点上,不是语法错,而是环境没配好:
- 查状态:
SELECT status FROM dba_tablespaces WHERE tablespace_name = 'E3_INDX';—— 必须返回ONLINE,READ ONLY不行 - 算空间:
SELECT SUM(bytes)/1024/1024 FROM dba_free_space WHERE tablespace_name = 'E3_INDX';—— 结果必须 ≥ 原索引大小 × 1.2(重建过程要双写) - 看权限:执行用户必须有
ALTER ANY INDEX,普通业务用户连上去跑脚本必报 ORA-01031
哪些索引重建会静默失败或报怪错
不是所有索引都能无脑 REBUILD ONLINE,这几类必须提前识别:
- 含
LOB或VARCHAR2(MAX)列的表上的索引:会报 ORA-01702,只能脱机重建(停业务)或换方案 - 函数索引、域索引、IOT 主键索引:部分版本不支持
ONLINE,报 ORA-00439 或 ORA-01438 - 全局临时表上的索引:
REBUILD会报 ORA-14452,这类索引本就不该长期存在
重建完成后别忘了做两件事:一是用 RESIZE 收缩原数据文件释放磁盘,二是检查 DBA_INDEXES 确认 tablespace_name 已更新——因为重建失败时语句可能部分执行,表空间字段不会回滚。











