先查user_indexes和user_ind_partitions确认索引类型:若partitioned='YES'且index_type='NORMAL',多为GLOBAL索引,整体UNUSABLE需全量REBUILD;若user_ind_partitions有记录且个别分区STATUS='UNUSABLE',则为LOCAL索引,可单分区重建。

查清是全局索引还是本地索引的分区失效
UNUSABLE 状态在本地索引(LOCAL)和全局索引(GLOBAL)中含义完全不同,修复路径也完全分离。不先确认类型就执行 REBUILD PARTITION,大概率触发 ORA-14086 错误。
用这两条语句快速区分:
SELECT index_name, index_type, partitioned, status FROM user_indexes WHERE table_name = 'YOUR_TABLE';
SELECT index_name, partition_name, status FROM user_ind_partitions WHERE index_name = 'YOUR_INDEX';
- 若
user_indexes.partitioned = 'YES'且index_type = 'NORMAL'→ 很可能是 GLOBAL 分区索引(注意:Oracle 12c 的 GLOBAL 索引本身不分区,所谓“全局分区索引”是误称;真正分区的是 LOCAL 索引) - 若
user_indexes.partitioned = 'YES'且index_type = 'DOMAIN'或查user_ind_partitions有记录 → 是 LOCAL 索引,每个分区独立维护 -
user_ind_partitions.status = 'UNUSABLE'但user_indexes.status = 'VALID'→ 局部问题,可单分区重建 -
user_indexes.status = 'UNUSABLE'→ 整个索引已不可操作,REBUILD PARTITION直接报错,必须先全量REBUILD
本地索引分区失效:先验证状态再重建
本地索引的分区与表分区一一绑定,某个分区索引失效(比如因 EXCHANGE PARTITION 未带 INCLUDING INDEXES),不会自动让整个索引变 UNUSABLE —— 但一旦你手动执行过 ALTER INDEX ... UNUSABLE,或迁移/导入过程出错,就可能整体失效。
- 执行
ALTER INDEX idx_name REBUILD PARTITION p_name前,务必确认user_indexes.status = 'VALID' - 如果
user_ind_partitions.status只有个别分区为UNUSABLE,而其他都是USABLE,直接重建那个分区即可 - 重建命令建议带上
ONLINE(仅限非唯一 LOCAL 索引):ALTER INDEX idx_name REBUILD PARTITION p_name ONLINE; - 不加
ONLINE会锁住该分区对应的数据段,DML 阻塞;加了则需额外临时空间,失败时可能残留TEMPORARY对象,记得查USER_OBJECTS清理
全局索引失效:不能用 REBUILD PARTITION
全局索引(GLOBAL)没有分区视图,user_ind_partitions 查不到它的任何记录。它是一个整体 B-tree 结构,删一个分区、TRUNCATE PARTITION 或 MOVE 表都可能导致其直接变为 UNUSABLE,且无法按“分区”重建。
-
ALTER INDEX idx_name REBUILD PARTITION xxx对全局索引语法非法,会报ORA-02149(invalid partition name)或类似错误 - 正确做法只有两步:
ALTER INDEX idx_name UNUSABLE;(毫秒级,不阻塞 DML),再ALTER INDEX idx_name REBUILD TABLESPACE ts_name PARALLEL 4; - 千万别信
UPDATE GLOBAL INDEXES能修复已发生的失效——它只是 DDL 子句,只影响后续操作(如DROP PARTITION UPDATE GLOBAL INDEXES),对当前UNUSABLE状态完全无效 - 重建时加
ONLINE对 GLOBAL 索引无效(Oracle 不支持),强行加会忽略或报错
重建后必须验证是否真可用
状态列从 UNUSABLE 变成 USABLE 不代表索引能被优化器选中。尤其在分区表场景下,统计信息滞后或执行计划缓存可能掩盖真实问题。
- 执行
SELECT /*+ INDEX(t idx_name) */ COUNT(*) FROM your_table t WHERE indexed_col = :val;,看是否走索引(EXPLAIN PLAN检查) - 检查
DBA_INDEXES.domidx_status(函数索引依赖)和funcidx_status,排除隐式失效 - 大规模重建后,建议立刻收集统计信息:
EXEC DBMS_STATS.GATHER_INDEX_STATS('OWNER', 'IDX_NAME'); - 如果重建后仍报
ORA-01502,大概率是应用连接没刷新执行计划缓存,或存在物化视图日志、IOT 主键等间接依赖未处理


















