Oracle不支持在物化视图上创建LOCAL索引,仅支持GLOBAL索引;即使基表分区,物化视图默认仍是非分区堆表,CREATE INDEX ... LOCAL会报ORA-02158错误;所谓“本地效果”实为分区裁剪配合GLOBAL索引实现。

物化视图本地索引根本不会被创建
Oracle 不支持在物化视图上创建 LOCAL 索引——LOCAL 是分区表索引的属性,而物化视图即使建在分区基表上,其本身仍是普通堆表(或 IOT),没有分区段结构。你执行 CREATE INDEX ... LOCAL 会直接报错 ORA-02158: invalid CREATE INDEX option。所谓“物化视图本地索引”是个常见误解,实际只能建 GLOBAL 索引,或对分区物化视图使用 LOCAL 的前提是它已被显式声明为分区表(通过 PARTITION BY 子句创建),但这在 19c 及之前版本中不被支持。
物化视图分区后才能建真正 LOCAL 索引
只有当你用 CREATE MATERIALIZED VIEW ... PARTITION BY RANGE/LIST/... 显式定义分区键,并且数据库版本 ≥ 21c(或 19c 后期补丁集启用隐藏参数),才可能让物化视图拥有分区段,从而允许 LOCAL 索引。但绝大多数生产环境仍在 19c 或 12c,此时:
- 即使基表是分区表,物化视图默认仍是单个非分区段
- CREATE INDEX idx ON mv(col) LOCAL 语法非法
- 试图绕过限制(如先建分区表再 CREATE MATERIALIZED VIEW ON PREBUILT TABLE)需严格匹配分区定义、键约束和统计信息,极易失败
你以为的“本地效果”其实是分区裁剪 + 全局索引
如果你观察到查询只扫物化视图的某几个分区,那不是因为用了 LOCAL 索引,而是:
- 物化视图本身按时间等字段做了范围分区(PARTITION BY RANGE(sales_month))
- 查询谓词精确匹配分区键(如 WHERE sales_month = '2026-08'),触发分区裁剪(Partition Pruning)
- 配合在 (customer_id, sales_month) 上建的 GLOBAL 索引,优化器走 INDEX RANGE SCAN + PARTITION LIST SINGLE
- 此时 EXPLAIN PLAN 中 OBJECT_PARTITION 有值,但 INDEX_NAME 下始终显示 GLOBAL 索引名,绝不会出现 LOCAL
真正该检查的三个地方
当物化视图查询没走索引,别盯着“本地”二字,先确认:
- SELECT STATUS FROM DBA_INDEXES WHERE INDEX_NAME = 'YOUR_IDX_NAME' 返回 UNUSABLE?必须 ALTER INDEX ... REBUILD
- SELECT LAST_ANALYZED FROM DBA_TAB_STATISTICS WHERE TABLE_NAME = 'YOUR_MV_NAME' 是否刷新后未更新?得 DBMS_STATS.GATHER_TABLE_STATS(..., cascade => TRUE)
- 查询条件是否碰了索引失效雷区:函数(UPPER(name))、隐式转换(id = '123')、IS NULL 在复合索引非首列、或 LIKE '%abc'
真正卡住人的,往往是花了半天排查“为什么 LOCAL 索引不生效”,结果发现压根没这玩意儿——Oracle 对物化视图的索引支持,始终停留在 GLOBAL 层面,所有“本地感”都来自分区裁剪与全局索引的协同,而非索引本身的 locality。


















