Direct Path Load 使 local 索引失效是因为其绕过常规 DML 路径,不触发逐行索引维护,Oracle 为避免查询返回脏数据,将对应分区索引状态设为 UNUSABLE;需显式指定 UPDATE INDEXES(SQL*Loader)或手动 ALTER INDEX ... REBUILD PARTITION 恢复。

Direct Path Load(如 SQL*Loader DIRECT=TRUE 或 INSERT /*+ APPEND */)会直接绕过 buffer cache 写入数据段,此时局部索引(local index)不会自动维护 —— 即使是本地索引,也会被标记为 UNUSABLE,除非显式指定 UPDATE INDEXES。
为什么 Direct Path Load 会让 local 索引失效?
Direct Path Load 不走常规的 DML 路径,不触发索引的逐行插入逻辑。Oracle 无法在加载过程中同步构建索引条目,所以它选择“先写数据、后建索引”的策略:把对应分区的本地索引分区状态设为 UNUSABLE,避免查询走错索引返回脏数据。
- 即使只加载一个分区(例如用
PARTITION (p2024)子句),该分区对应的 local 索引分区仍会变成UNUSABLE -
USER_IND_PARTITIONS.STATUS字段会显示UNUSABLE,不是N/A(后者仅表示未收集统计信息) - 后续查询若依赖该索引,会报
ORA-01502: index ... or partition of such index is in unusable state
SQL*Loader 中如何保持 local 索引可用?
必须在控制文件中显式启用 UPDATE INDEXES,否则默认不维护任何索引。
- 语法位置在
LOAD DATA后、INFILE前:LOAD DATA UPDATE INDEXES ... - 只对 local 索引有效;global 索引仍会失效(
UPDATE INDEXES对 global 无效,需另加UPDATE GLOBAL INDEXES) - 该选项会触发 Oracle 在 load 完成后自动重建所有受影响的 local 索引分区 —— 意味着额外的 CPU 和 I/O 开销,且期间索引不可用
- 若控制文件里漏写
UPDATE INDEXES,load 完成后必须手动执行:ALTER INDEX idx_name REBUILD PARTITION p2024;
INSERT /*+ APPEND */ 场景下 local 索引怎么处理?
这个操作本身不提供索引维护开关,/*+ APPEND */ 只影响数据写入路径,索引状态完全由后续动作决定。
- 执行后立即查
USER_IND_PARTITIONS,大概率看到UNUSABLE - 不能靠
COMMIT恢复索引 —— 这和普通 INSERT 不同,append 是 bulk 操作,commit 不触发索引修复 - 必须主动重建:
ALTER INDEX idx_name REBUILD PARTITION p2024;或全分区重建:ALTER INDEX idx_name REBUILD; - 如果表有多个分区被 append 加载,建议用并行重建:
ALTER INDEX idx_name REBUILD PARTITION p2024 PARALLEL 4;
容易被忽略的关键点
很多人以为 “local 就是自动维护”,但在 Direct Path 场景下这个假设完全不成立。最常踩的坑是:load 完了没检查索引状态,第二天业务突然慢或报 ORA-01502,才发现所有 local 索引分区都是 UNUSABLE。更隐蔽的是,有些监控只查 USER_INDEXES.STATUS(主索引状态),但 local 索引的主状态永远是 VALID,真正要看的是 USER_IND_PARTITIONS.STATUS —— 每个分区的状态才是实际可用性依据。











