Oracle 分区索引的状态必须分层检查:全局索引先看 user_indexes.status,本地索引还需要进一步查询 user_ind_partitions 确认每个分区的 status。原因在于 user_indexes 对局部索引分区失效并不敏感,很多时候只显示整体 VALID,但实际上某些索引分区可能已经处于 UNUSABLE 状态,甚至存在分区缺失的问题。

查哪些索引或分区真的不可用了
不要只盯着 user_indexes.status,对于 Oracle 分区索引来说,这个视图对部分场景存在“盲点”——全局索引状态通常能够准确反映,但如果本地索引(LOCAL)只是某个分区失效,user_indexes.status 依然可能显示为 VALID。因此,排查 Oracle 索引 UNUSABLE 状态时,必须按层级逐步核查:
- 全局索引:直接执行
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE' AND index_type = 'NORMAL';如果结果中status = 'UNUSABLE',通常就需要整体重建索引 - 本地索引:先查看整体状态是否异常:
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE' AND partitioned = 'YES';然后继续检查具体分区:SELECT index_name, partition_name, status FROM user_ind_partitions WHERE index_name = 'YOUR_IDX' - 函数索引或位图索引:还要额外关注
funcidx_status和index_type字段,不过大多数UNUSABLE问题本质上仍然来自分区相关 DDL 操作,而不是函数依赖失效
ALTER INDEX REBUILD PARTITION 报 ORA-14086 怎么办
遇到这个报错,通常不是 SQL 语法写错了,而是你正在对一个整体已经处于 UNUSABLE 状态的本地索引,强行执行单个分区重建。Oracle 对此有明确限制:只要 user_indexes.status 显示为 UNUSABLE,就不能直接使用 REBUILD PARTITION。
- 第一步先执行
ALTER INDEX idx_name REBUILD—— 该命令会重建整个本地索引,把所有索引分区一并恢复到VALID状态 - 整体重建完成后,立即检查
user_ind_partitions.status;如果仍有个别分区显示为UNUSABLE(这种情况较少,通常出现在中断或异常残留后),再有针对性地执行ALTER INDEX idx_name REBUILD PARTITION p_name - 不要试图跳过整体重建。想直接用
REBUILD PARTITION绕过 Oracle 的限制,只会持续触发ORA-14086错误
重建时加 ONLINE 安全吗
ONLINE 并不是 Oracle 索引重建的万能选项,它只在特定类型的分区索引场景下才真正有效,盲目添加反而容易带来新的问题:
- 只对本地索引(
LOCAL)有效;如果是全局索引执行REBUILD或REBUILD PARTITION时加上ONLINE,可能被 Oracle 忽略,某些版本下甚至会直接报错 - 唯一性本地索引(
UNIQUE LOCAL)不支持ONLINE REBUILD PARTITION;即使语法校验通过,执行过程中也很可能失败 - 底层会创建临时段并回放 DML,导致 IO 压力和临时表空间占用显著上升;一旦空间不足,可能残留一个
TEMPORARY状态的对象,需要手动到USER_OBJECTS中排查并清理 - 索引重建完成后一定要做验证:仅仅看到
status = 'USABLE'还不够,还应执行EXPLAIN PLAN确认 SQL 实际是否使用该索引,同时检查统计信息是否已更新
为什么 UPDATE INDEXES 补救不了已发生的 UNUSABLE
UPDATE INDEXES(或 UPDATE GLOBAL INDEXES)本质上并不是 Oracle 索引修复命令,它只是分区 DDL 执行时的“同步维护选项”。一旦像 DROP PARTITION 这样的操作已经执行结束,并且索引状态已经变成 UNUSABLE,这个子句就无法再起补救作用。
- 它只对当前正在执行的那一条 DDL 语句有效,而且仅适用于
DROP、EXCHANGE、SPLIT、MERGE、MOVE、TRUNCATE这些操作;像ADD PARTITION或RENAME这类语句,即使加上也没有实际效果 - 语法位置必须紧跟主语句之后、分号之前,中间不能插入换行或注释,否则 Oracle 可能直接忽略这个子句
- 如果 DDL 执行过程中因为空间不足、约束冲突等原因失败,可能出现事务已回滚,但部分索引状态仍被标记为
UNUSABLE的情况;这种“半损坏”状态只能通过人工检查和手动重建处理
真正容易被忽略的一点是:即使状态列已经恢复为 USABLE,CBO 仍可能因为统计信息过旧而不选择该索引,最终出现“看似修复完成,实际查询并未走索引”的问题。因此,Oracle 索引修复完成后如果不及时收集统计信息,这次修复其实只完成了一半。
