局部前缀索引在查询含分区键且为索引首列时性能更优,能精准分区裁剪;不含分区键时全局索引更高效,支持单点查找;全局索引须前缀,update global indexes 有性能代价,部分索引和全表唯一约束设计需前置考量。
没有“哪个性能更好”的通用答案——性能完全取决于查询谓词是否能触发分区裁剪,以及该谓词是否落在索引键的前导位置。
WHERE 条件含分区键时,局部前缀索引通常更优
当查询条件包含表的分区键(如 WHERE sale_date BETWEEN ...),且该列是局部索引的首列(前缀索引),Oracle 能精准定位到 1–N 个目标分区,跳过其余分区的 I/O。
- 局部索引每个分区独立维护,B-tree 高度低、缓存友好;全局索引即使覆盖全表,也可能因跨分区指针导致逻辑读放大
- 例如:按
sale_dateRANGE 分区的表,建CREATE INDEX idx_local ON sales(sale_date, customer_id) LOCAL,查WHERE sale_date = DATE'2025-03-01'只扫一个分区索引段 - 若误用全局索引(哪怕也是
sale_date前导),仍需扫描整个 B-tree,无法裁剪——除非用GLOBAL PARTITION BY RANGE(sale_date),但此时它已退化为“按表分区对齐的全局索引”,失去跨分区聚合优势
WHERE 条件不含分区键时,全局索引大概率胜出
一旦查询只过滤非分区键字段(如 WHERE customer_id = 123),局部索引被迫全分区扫描,而全局索引单次 B-tree 查找即可定位全部匹配行。
- 局部非前缀索引(如
CREATE INDEX idx_noprefix ON sales(customer_id) LOCAL)无法利用分区裁剪,执行计划中会出现PARTITION RANGE ALL,I/O 成倍增加 - 全局索引(
CREATE INDEX idx_global ON sales(customer_id) GLOBAL)无论表如何分区,都保持单点查找能力 - 注意:全局索引必须是前缀的——若建
GLOBAL PARTITION BY RANGE(customer_id),则customer_id必须是索引定义的首列,否则报错ORA-14038: global partitioned index must be prefixed
UPDATE GLOBAL INDEXES 不是银弹,要权衡 DDL 延迟与可用性
在需要频繁 DROP/TRUNCATE 分区的场景下,有人倾向加 UPDATE GLOBAL INDEXES 保全局索引可用,但这会显著拖慢 DDL 执行时间,并消耗大量临时表空间。
-
ALTER TABLE t DROP PARTITION p2025 UPDATE GLOBAL INDEXES本质是边删数据边更新所有全局索引条目,对亿级表可能延长操作数分钟甚至小时 - 若业务允许短时索引不可用,不如省略该子句,后续异步重建:
ALTER INDEX idx_global REBUILD ONLINE(需企业版) - Oracle 12c+ 的部分索引(
INDEXING OFF)可规避此问题:对冷分区禁用索引,热分区保留全局索引,既降维护开销,又避免全表扫描
真正容易被忽略的是索引唯一性约束的隐含前提——局部索引只能保证“分区内部唯一”,若业务要求全表唯一(比如主键或唯一业务码),必须把分区键加入约束列,否则建索引会失败或逻辑出错。这点在设计阶段不验证,上线后改结构成本极高。











