Oracle物化视图不支持LOCAL索引,所谓“本地效果”实为分区裁剪配合GLOBAL索引实现;CREATE INDEX ... LOCAL在MV上必报ORA-02158;MV需显式定义PARTITION BY且查询谓词须严格匹配分区键。

Oracle物化视图根本不能建LOCAL索引——你看到的“本地效果”其实是分区裁剪配合GLOBAL索引实现的,不是索引类型带来的优化。
CREATE INDEX LOCAL在物化视图上直接报错ORA-02158
执行CREATE INDEX idx_mv_local ON mv(col) LOCAL一定会失败。因为LOCAL是分区表的索引属性,而物化视图默认是非分区堆表(哪怕基表是分区表)。19c及更早版本不支持对物化视图声明PARTITION BY,也就没有分区段结构供LOCAL索引依附。
常见误操作包括:
- 复制基表的分区DDL,直接套用到物化视图上,忽略
PARTITION BY子句在MV创建语法中需显式写出且受版本限制 - 试图用
ON PREBUILT TABLE先建分区表再关联MV,但未严格匹配分区键、边界值、约束和统计信息,导致后续索引或刷新失败 - 查
DBA_INDEXES发现索引状态为UNUSABLE,却误以为是“LOCAL索引坏了”,实际它压根没被创建过
所谓“局部扫描”其实是分区裁剪 + GLOBAL索引组合生效
当你观察到查询只访问物化视图的部分分区,并不代表用了LOCAL索引。真实链路是:
- 物化视图必须显式定义为分区表:
CREATE MATERIALIZED VIEW mv PARTITION BY RANGE(sales_month) - 查询谓词必须与分区键**完全一致**:列名大小写、是否带双引号、无任何函数包装(如不能用
TRUNC(dt),必须用dt本身) - 在分区键+高选择性列上建GLOBAL索引,例如
CREATE INDEX idx_mv_global ON mv(customer_id, sales_month) GLOBAL - 执行计划中
OBJECT_PARTITION显示具体分区号(如3),但INDEX_NAME下始终是GLOBAL索引名
真正该检查的三个关键点
别纠结“为什么LOCAL索引没生效”,先确认以下三项是否就绪:
-
SELECT STATUS FROM DBA_INDEXES WHERE INDEX_NAME = 'YOUR_IDX_NAME'返回VALID?若为UNUSABLE,必须ALTER INDEX ... REBUILD -
SELECT LAST_ANALYZED FROM DBA_TAB_STATISTICS WHERE TABLE_NAME = 'YOUR_MV_NAME'是否在最近一次刷新后更新?未收集会导致优化器误判成本,跳过索引 - 用
EXPLAIN PLAN FOR SELECT ... FROM mv WHERE sales_month = DATE '2026-08-01',确认OBJECT_NAME是物化视图名,且PARTITION_START/PARTITION_STOP不是KEY而是具体数字
最易被忽略的是:物化视图分区定义与查询谓词之间那一个空格、一个大小写、一个隐式类型转换,都会让分区裁剪失效——此时优化器连物化视图都不会访问,更别说索引了。


















