物化视图未被重写是因为优化器“不敢用”或“没发现能用”:会话级QUERY_REWRITE_ENABLED=FALSE、基表缺主键或MV日志缺失、MV状态STALE/UNUSABLE、查询列超出MV定义、建MV时未显式启用ENABLE QUERY REWRITE、统计信息未收集。

物化视图无法自动重写含聚合、连接或函数转换的复杂查询——Oracle 12c 的查询重写器对语义等价性要求极严,稍有不匹配(如列别名不同、WHERE 条件含未包含列、聚合粒度不一致)就会跳过 MV,直接扫基表。
为什么 EXPLAIN PLAN 显示还在扫基表,而不是 MV?
这不是配置没开,而是优化器“不敢用”或“没发现能用”。常见真实原因包括:
-
QUERY_REWRITE_ENABLED在会话级被设为FALSE(比如应用连接池里执行了ALTER SESSION SET QUERY_REWRITE_ENABLED = FALSE),压倒了系统级TRUE -
QUERY_REWRITE_INTEGRITY是默认的ENFORCED,但基表缺已验证的主键约束,或物化视图日志缺失(报错ORA-23413就是信号) - 物化视图状态是
STALE或UNUSABLE:查USER_MVIEWS中的STALENESS和STALENESS字段,NOT STALE才可能被考虑 - SQL 中用了物化视图里没有的列,比如 MV 只选了
region, SUM(sales),但查询写了WHERE order_date > SYSDATE-7——order_date不在 MV 定义中,重写直接失效
CREATE MATERIALIZED VIEW 时必须显式加 ENABLE QUERY REWRITE
建 MV 时不带这个子句,后续无法用 ALTER 补上——只能删掉重建。且必须配合全局参数生效:
- 系统级开关:确保
QUERY_REWRITE_ENABLED = TRUE(FORCE可绕过部分限制,但不推荐) - 对象级开关:建 MV 必须写成
CREATE MATERIALIZED VIEW mv_sales ENABLE QUERY REWRITE AS SELECT ... - 验证是否启用成功:查
USER_MVIEWS的QUERY_REWRITE_ENABLED列,值应为ENABLED
漏掉任一环节,DBMS_MVIEW.EXPLAIN_REWRITE 都会返回 REWRITE_CANNOT_BE_USED,连尝试都不做。
如何确认某条 SQL 真正被重写了?
别信 EXPLAIN PLAN FOR 的静态输出,它不保证真实执行路径。必须结合运行时证据:
- 开启
autotrace on explain后执行查询,看执行计划中OBJECT_NAME列是否出现你的 MV 名(如MV_SALES_SUM),而非基表名(如SALES) - 查
V$SQL_PLAN:过滤该 SQL 的SQL_ID,确认OBJECT_NAME字段是 MV 物理表名 - 用诊断工具:执行
DBMS_MVIEW.EXPLAIN_REWRITE('SELECT ...', 'MV_NAME'),输出结果会明确告诉你失败原因,比如no match、stale data或integrity violation
最常被忽略的是统计信息缺失:即使 MV 状态合法、参数全开,若没对 MV 物理表执行 DBMS_STATS.GATHER_TABLE_STATS,优化器因成本估算失真,仍可能弃用它。


















