局部索引在分区操作中天然保持可用,因其与表分区一一绑定、生命周期同步;全局索引因不感知分区结构,DROP等操作后易失效,需显式UPDATE GLOBAL INDEXES或重建。
局部索引在分区操作中天然保持可用,全局索引则极易因一次 drop partition 就变成 unusable 状态——这不是配置问题,是设计模型决定的。
局部索引如何自动响应表分区变更
Oracle 对局部索引的维护是隐式且绑定的:每个表分区都有唯一对应的索引分区,二者生命周期严格对齐。
- 执行
ALTER TABLE t DROP PARTITION p1时,对应索引分区自动删除,DBA_INDEXES.STATUS仍为VALID - 执行
ALTER TABLE t TRUNCATE PARTITION p2后,该分区索引段清空,但索引整体状态不变,无需人工干预 - 新增表分区(如
ADD PARTITION p5)时,Oracle 自动创建同名索引分区,无需额外ALTER INDEX ... ADD PARTITION - 局部索引重建可粒度到分区级:
ALTER INDEX idx_local REBUILD PARTITION p3,不影响其他分区查询
全局索引为何在分区维护后常变 UNUSABLE
全局索引不感知表分区结构,所有索引条目统一组织。一旦底层数据物理位置变动(如分区被删、移动、交换),索引指针即失效。
-
DROP PARTITION、SPLIT PARTITION、EXCHANGE PARTITION等操作默认使全局索引进入UNUSABLE状态,查询报错ORA-01502: index ... or partition of such index is in unusable state - 必须显式加
UPDATE GLOBAL INDEXES才能避免失效,但该子句会显著拖慢 DDL 执行时间,且要求足够临时表空间 - 若漏加
UPDATE GLOBAL INDEXES,后续只能重建:ALTER INDEX idx_global REBUILD—— 这是全索引扫描+排序,对亿级表可能耗时数小时 - 无法按分区重建:
REBUILD PARTITION对全局索引无效,语法报错ORA-14057: partition name must be specified for local index
局部非前缀索引的适用边界与陷阱
局部索引虽易维护,但并非万能。当查询条件不含分区键时,可能触发全分区扫描,性能反不如全局索引。
- 假设表按
sale_date范围分区,建了局部索引CREATE INDEX idx_local ON sales(customer_id) LOCAL(非前缀) - 执行
SELECT * FROM sales WHERE customer_id = 123时,Oracle 必须扫描所有分区的该索引段,I/O 放大 - 此时若改用全局索引
CREATE INDEX idx_global ON sales(customer_id) GLOBAL,单次 B-tree 查找即可定位全部匹配行 - 但要注意:全局索引列不能是非前缀的区间分区键——
CREATE INDEX ... GLOBAL PARTITION BY RANGE (customer_id)合法;而PARTITION BY RANGE (sale_date)但索引列不含sale_date会报ORA-14038: global partitioned index must be prefixed
真正影响维护成本的不是“是否分区”,而是“谁负责同步”
局部索引的“易维护”本质是 Oracle 把同步逻辑下沉到了存储层;全局索引把一致性责任推给了 DBA。很多团队踩坑,是因为在 OLTP 场景误用局部索引,在 DSS 场景又忽略 UPDATE GLOBAL INDEXES 的开销。
- 数据仓库类批量加载场景:优先局部索引,禁用再重建比维护全局索引快一个数量级
- 高频单分区查询(如查某天订单):局部前缀索引(
(sale_date, order_id))最稳 - 跨时间范围查客户行为(如“某客户近6个月所有订单”):必须用全局索引,但要提前规划好分区维护窗口和重建资源
- 最容易被忽略的一点:
ALTER INDEX ... UNUSABLE后若未及时REBUILD,应用侧可能静默降级为全表扫描,监控上只体现为逻辑读飙升,而非报错


















