Oracle分区表MOVE后索引必然失效,因ROWID重写导致所有索引(全局/本地)变为UNUSABLE;需查user_indexes和user_ind_partitions确认状态,本地索引须逐分区REBUILD,全局索引需先UNUSABLE再REBUILD。

Oracle分区表移动后索引失效不是意外,是ROWID重写后的必然结果——只要执行了ALTER TABLE ... MOVE或MOVE PARTITION,所有依赖原物理地址的索引(无论全局/本地、唯一/普通)都会变成UNUSABLE状态,后续查询或DML一旦触碰该索引就报ORA-01502。
怎么确认哪些索引真失效了
别靠猜,直接查user_indexes和user_ind_partitions:
-
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE';—— 全局索引看这里,status = 'UNUSABLE'就是它 -
SELECT index_name, partition_name, status FROM user_ind_partitions WHERE index_name IN (SELECT index_name FROM user_indexes WHERE table_name = 'YOUR_TABLE' AND index_type = 'NORMAL');—— 本地索引必须逐分区查,status不是USABLE就得处理 - 注意:
funcidx_status = 'DISABLED'和分区无关,不用管;status字段才是关键
重建本地索引(LOCAL)要按分区操作
本地索引段和分区一一绑定,不能只REBUILD整个索引名,否则会报错或漏重建:
- 对单个分区重建:
ALTER INDEX idx_name REBUILD PARTITION part_name TABLESPACE ts_name; - 想批量生成语句?用这个脚本:
SELECT 'ALTER INDEX ' || index_name || ' REBUILD PARTITION ' || partition_name || ' TABLESPACE users;' FROM user_ind_partitions WHERE index_name IN (SELECT index_name FROM user_indexes WHERE table_name = 'T1') AND status != 'USABLE'; - 大分区加
PARALLEL提速:ALTER INDEX idx_name REBUILD PARTITION p1 TABLESPACE users PARALLEL 4;,完事后记得ALTER INDEX idx_name NOPARALLEL;归还并行度 - 别用
UPDATE GLOBAL INDEXES——它对本地索引无效,语法也不支持
修复全局索引(GLOBAL)必须两步走
直接REBUILD可能失败(ORA-01408),先置为UNUSABLE再重建才是稳解:
- 第一步(毫秒级,几乎不锁表):
ALTER INDEX global_idx UNUSABLE; - 第二步(耗时操作,选窗口期):
ALTER INDEX global_idx REBUILD TABLESPACE users PARALLEL 4 LOGGING; - 如果空间紧张,去掉
LOGGING;若需最小化锁,加ONLINE(12cR2+),但要求表有主键且无LONG列 -
UPDATE GLOBAL INDEXES只在DROP/EXCHANGE/SPLIT等DDL里有效,对已发生的MOVE失效完全没用,别试
移动分区表前最容易被忽略的三件事
MOVE操作本身不难,但配套动作漏一项就踩坑:
- LOB字段必须单独处理:
ALTER TABLE t MOVE LOB(col) STORE AS (TABLESPACE ts_name);,否则LOB段还在原表空间,MOVE后查LOB列会报错 - 统计信息不会自动更新:
DBMS_STATS.GATHER_TABLE_STATS得手动跑,否则执行计划可能误判 - 物化视图日志会阻塞MOVE:
SELECT * FROM user_mview_logs WHERE master = 'YOUR_TABLE';,有就先DROP,MOVE完再重建


















