应加 UPDATE GLOBAL INDEXES 子句,否则全局索引静默失效导致 ORA-01502 错误;Oracle 默认不维护以提升性能,加该子句可在线维护索引,适用于业务不可中断且索引数据量不大的场景。
UPDATE GLOBAL INDEXES 子句到底该不该加
加。不加就失效,而且是静默失效——alter table ... drop partition 或 exchange partition 执行成功,但全局索引立刻变成 unusable 状态,后续查询直接报错 ora-01502: index ... or partition of such index is in unusable state。
Oracle 默认不维护全局索引,这是为了性能让步:分区 DDL 是高开销操作,重建索引会锁表、拖慢执行时间。所以它把选择权交给你——要么手动重建(停业务),要么加 UPDATE GLOBAL INDEXES 让 Oracle 边改分区边修索引。
- 适用场景:线上业务不能停、索引数据量不大(
- 不适用场景:超大表(TB 级)+ 高频写入 + 严格 SLA,此时加该子句可能导致 DDL 卡住或引发大量 I/O 压力
- 注意:
UPDATE GLOBAL INDEXES不支持TRUNCATE PARTITION,只能用于DROP/EXCHANGE/SPLIT/MERGE
为什么有时加了还是报 ORA-01502
常见原因是索引本身已有 UNUSABLE 分区,或者操作过程中发生中断(比如被 kill、实例崩溃),导致索引状态卡在中间态。Oracle 不会自动回滚索引修复动作,只回滚表结构变更。
- 执行前先查:
SELECT index_name, status, funcidx_status FROM user_indexes WHERE index_type = 'NORMAL' AND table_name = 'YOUR_TABLE'; - 如果看到
UNUSABLE,别硬上 DDL,先用ALTER INDEX ... REBUILD或ALTER INDEX ... REBUILD PARTITION ...清理干净 -
UPDATE GLOBAL INDEXES过程中若失败,索引大概率残留为UNUSABLE,必须显式重建,不能重试原 DDL
和 LOCAL 索引比,GLOBAL 的维护成本在哪
根本区别在于数据分布:LOCAL 索引每个分区对应一个独立段,删分区等于删掉整个索引分区;GLOBAL 索引是跨分区的 B-tree,一条索引条目可能指向任意分区里的行。所以删分区时,Oracle 必须扫描并清理所有指向该分区的索引条目——这就是 UPDATE GLOBAL INDEXES 实际干的事。
- 性能影响:DML 并发越高、全局索引键值越分散,清理耗时越长;实测单次
DROP PARTITION加该子句,可能比不加慢 3–10 倍 - 锁范围:操作期间,全局索引会被短暂加
SRX锁(Share Row eXclusive),阻塞部分 DML,但不会阻塞 SELECT - 空间开销:重建过程需要额外临时空间,约为索引当前大小的 1.2–1.5 倍
替代方案:不加子句,但避免索引失效
真不能加 UPDATE GLOBAL INDEXES?可以分两步走:先标记索引为 UNUSABLE(快速),再异步重建(可控)。
- 步骤一:
ALTER INDEX idx_name UNUSABLE;(秒级,无锁) - 步骤二:
ALTER TABLE t DROP PARTITION p1;(快,不碰索引) - 步骤三:
ALTER INDEX idx_name REBUILD ONLINE;(后台跑,支持 DML,但需额外空间) - 关键点:重建必须用
ONLINE,否则会锁全表;且REBUILD不能指定PARTITION(因为是 GLOBAL)
这个流程把风险拆开了:分区操作不再受索引拖累,重建失败也不影响表可用性,只是查询暂时走不了索引——得提前跟业务方对齐降级预期。










