query_rewrite_enabled必须为true,否则物化视图永不被重写;根本原因常是优化器不敢用或未发现可用,需检查query_rewrite_integrity设置、约束验证、物化视图日志、sql语义匹配及会话级参数覆盖。

QUERY_REWRITE_ENABLED 必须为 TRUE,否则物化视图再完整也永远不会被重写使用。这是整个机制启动的开关,不是可选项。
为什么物化视图建好了,查询却没走它?
常见现象:执行计划里完全看不到物化视图表名,EXPLAIN PLAN 显示仍在扫基表,哪怕物化视图数据已就位、刷新正常。
根本原因通常是优化器“不敢用”或“没发现能用”。排查要点:
-
QUERY_REWRITE_INTEGRITY值为ENFORCED(默认)时,要求基表必须有 已验证(validated)的主键/外键约束,且物化视图日志需存在并启用;缺一不可 - 物化视图定义中用了
SYSDATE、ROWNUM、子查询含非确定性函数(如DBMS_RANDOM.VALUE),会导致重写被直接禁用 - 查询中的列别名、表达式写法与物化视图 SELECT 列不严格语义等价(例如物化视图用
UPPER(name),而查询写name),即使结果一致,也可能跳过重写 - 会话级参数被覆盖:
ALTER SESSION SET QUERY_REWRITE_ENABLED = FALSE会压倒系统级设置
如何确认某条 SQL 是否被重写?
别猜,用 Oracle 自带的诊断工具验证:
- 先运行
DBMS_MVIEW.EXPLAIN_REWRITE过程,传入你的 SQL 和物化视图名,它会输出详细理由——是“no match”、“stale data”还是“integrity violation” - 开启
autotrace on explain后执行查询,看执行计划中是否出现物化视图的物理表名(如MV_SALES_SUM);若只看到基表名(如SALES),说明未触发重写 - 查
V$SQL_PLAN中该 SQL 的OBJECT_NAME字段,确认实际访问对象
注意:EXPLAIN PLAN 本身不保证真实执行路径,务必结合 V$SQL_PLAN 或实际 autotrace 输出判断。
物化视图日志不是可选配件,而是 FAST 刷新和重写的硬依赖
报错 ORA-23413: table "SCHEMA"."TABLE" does not have a materialized view log 是典型信号——你试图用 REFRESH FAST,但基表没配日志。
创建日志不能只写 WITH ROWID 就完事,关键细节:
- 必须显式列出所有被物化视图引用的列,例如物化视图 SELECT 中用了
product_id, category, price,日志就要WITH ROWID, SEQUENCE (product_id, category, price) INCLUDING NEW VALUES - 如果物化视图含聚合(
SUM、COUNT(*)等),日志必须包含SEQUENCE,否则FAST刷新失败 - 多表连接场景下,**每张基表**都得有自己的物化视图日志,漏一个就卡住
权限问题常被忽略:CREATE MATERIALIZED VIEW LOG 需要 CREATE TABLE 权限,而不仅是 CREATE MATERIALIZED VIEW 权限。
QUERY_REWRITE_INTEGRITY 的三个值到底怎么选?
这不是性能开关,而是数据一致性策略。选错会导致结果错,不是慢的问题:
-
ENFORCED:最安全。要求约束已VALIDATE,物化视图数据必须fresh。适合金融、账务等强一致性场景 -
TRUSTED:允许用RELY DISABLE NOVALIDATE约束,且接受预构建(prebuilt)物化视图。适合 ETL 流程可控、人工保障数据关系的数仓环境 -
STALE_TOLERATED:连数据过期都容忍——只要物化视图存在,就敢重写。仅适用于报表类、容忍分钟级延迟的场景,且必须配合监控防止长期 stale
真正容易被忽略的是:修改 QUERY_REWRITE_INTEGRITY 后,**必须重新收集基表和物化视图的统计信息**,否则优化器成本估算失真,仍可能拒绝重写。











