全局索引显著拖慢INSERT性能是设计必然:每次插入需同步更新跨分区B-tree,引发锁竞争、页分裂与分布式协调开销。
全局索引会显著拖慢插入性能,这不是配置问题,而是设计必然——每次 insert 都必须同步更新跨越所有分区的 b-tree 结构,锁粒度更粗、io 路径更长、cpu 开销翻倍。
为什么 INSERT 会变慢:全局索引的写路径不可绕过
局部索引写入只影响当前分区的索引段;而全局索引要求每一行插入都定位到全局 B-tree 的正确叶子页,并可能触发跨分区的页分裂、合并与重平衡。这不是“多维护一个索引”,而是把单次写操作变成一次分布式协调动作。
- Oracle 中,
INSERT必须获取全局索引的TX锁 + 索引块的latch,高并发下极易出现enq: TX - index contention - 即使表是按
create_time范围分区,你在user_id上建了全局索引,新插入的行仍要跳转到整个索引树中user_id对应的位置——物理位置完全随机 -
NOLOGGING只跳过重做日志,不减少索引结构变更本身,且崩溃后索引直接UNUSABLE,反而增加恢复风险
ALTER TABLE ADD GLOBAL INDEX 期间发生了什么
不是“建索引慢”,而是建索引过程本身就在持续阻塞写入。Oracle 默认串行构建全局索引,全程持有 SS(sub-share)锁,任何 DML 都得排队等它释放。
- 执行
CREATE INDEX ... GLOBAL时,若表有 1 亿行,构建过程可能持续数小时;期间INSERT会卡在enq: TM - contention或直接超时报ORA-00054 -
PARALLEL 4可加速构建,但并行 worker 之间仍需协调全局索引结构,无法消除锁冲突本质 - 千万别在业务高峰期跑
ALTER TABLE ... ADD GLOBAL INDEX—— 它比加普通索引更危险,因为还隐含对所有分区元数据的校验
分区 DDL 操作让全局索引瞬间失效
只要动了分区定义,全局索引就大概率进入 UNUSABLE 状态,不是“暂时不可用”,而是优化器彻底拒绝走它——哪怕你刚重建完。
-
ALTER TABLE ... DROP PARTITION后,SELECT ... WHERE user_id = ?突然退化为全表扫描,EXPLAIN PLAN显示INDEX状态为UNUSABLE - 修复不是
ALTER INDEX ... REBUILD,而是必须在 DDL 语句里显式加UPDATE GLOBAL INDEXES子句(Oracle 12c+),否则索引元数据和物理结构脱节 - PostgreSQL 没原生全局索引概念,所谓“全局”只是应用层在每个子表上重复建同名索引,
ATTACH/DETACH不影响父表索引,但一致性全靠人工保障
真正容易被忽略的点是:全局索引的代价不在空间占用,而在每次写操作的锁竞争范围和事务可见性边界——它把原本局限在单个分区内的写冲突,放大成了整张表级别的资源争用。哪怕你只插一行,也得跟其他分区的写入者抢同一个索引根块。



















