QUERY_REWRITE_ENABLED必须为TRUE,否则物化视图永不被重写;需确认系统级参数为TRUE或FORCE、会话未被覆盖关闭、物化视图已启用查询重写、状态为NOT STALE且统计信息最新、SQL语义与物化视图严格匹配。

QUERY_REWRITE_ENABLED = FALSE 是最常见、最直接的原因——它关掉了整个重写机制的电源开关,其他所有配置都白搭。
QUERY_REWRITE_ENABLED 是否真为 TRUE
别只查 SHOW PARAMETER query_rewrite_enabled,它显示的是当前会话值,而会话级设置可以被 ALTER SESSION SET QUERY_REWRITE_ENABLED = FALSE 覆盖。必须确认两点:
- 系统级参数是
TRUE或FORCE:SELECT VALUE FROM V$PARAMETER WHERE NAME = 'query_rewrite_enabled' - 当前会话没被手动关掉:
SELECT SYS_CONTEXT('USERENV', 'SESSIONID') FROM DUAL后查V$SES_OPTIMIZER_ENV中对应会话的QUERY_REWRITE_ENABLED值 - 物化视图本身创建时带了
ENABLE QUERY REWRITE;若已存在,需执行ALTER MATERIALIZED VIEW mv_name ENABLE QUERY REWRITE
物化视图状态和统计信息是否合法可用
优化器看到 STALE 或 UNUSABLE 状态,或发现物化视图没统计信息,会直接跳过它——不是“不敢用”,而是“不认这个对象”。
- 查状态:
SELECT mview_name, staleness, compile_state FROM USER_MVIEWS WHERE mview_name = 'MV_NAME';staleness必须是NOT STALE(QUERY_REWRITE_INTEGRITY = ENFORCED时)或至少是STALE(= STALE_TOLERATED时) - 查统计:
SELECT table_name, last_analyzed, num_rows FROM USER_TAB_STATISTICS WHERE table_name = 'MV_NAME';若last_analyzed为空或远早于最近一次刷新时间,立刻执行DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'MV_NAME') - 注意:预建表(
ON PREBUILT TABLE)的统计必须收集到物理表名上,不是物化视图名
查询语义是否与物化视图严格匹配
Oracle 的重写不是模糊匹配,而是要求列、表达式、过滤条件三者在语法树层面可推导等价。一个括号、一个函数、大小写不一致,都会导致失败。
- 用
DBMS_MVIEW.EXPLAIN_REWRITE验证:EXEC DBMS_MVIEW.EXPLAIN_REWRITE('SELECT ... FROM base_table WHERE ...', 'MV_NAME'),然后查MV_CAPABILITIES_TABLE中的MESSAGE字段,看是no match、partition key not used还是expression not supported - WHERE 条件必须直接作用于物化视图 SELECT 列中的**物理列名**,不能是
TRUNC(dt)、NVL(dt, sysdate)、UPPER(name)——哪怕物化视图里也写了同样函数,只要列别名或表达式树不完全对齐,就失败 - 分区键列名必须一字不差(含双引号定义的大小写),且查询中不能有任何隐式类型转换,比如
WHERE sale_date = '2024-01-01'(字符串) vsWHERE sale_date = DATE '2024-01-01'(日期字面量)
执行计划里到底有没有走物化视图
别信 EXPLAIN PLAN FOR 单独输出,它不保证真实执行路径;要结合运行时实际计划和对象访问痕迹交叉验证。
- 开启
autotrace on explain后执行查询,看执行计划中OBJECT_NAME是基表名还是物化视图名;若出现MATERIALIZED VIEW REWRITE行,说明重写生效 - 查
V$SQL_PLAN:SELECT OBJECT_NAME, PARTITION_START, PARTITION_STOP FROM V$SQL_PLAN WHERE SQL_ID = 'xxx' AND OBJECT_NAME LIKE '%MV_NAME%';若PARTITION_START显示具体数字(如 3),而非KEY或ROW LOCATION,说明不仅走了 MV,还成功裁剪了分区 - 临时加 hint 测试:
SELECT /*+ REWRITE(MV_NAME) */ ...,如果执行计划立刻切过去且性能提升,基本锁定是 CBO 成本误判,而不是重写逻辑不通
真正卡住的地方往往不在“怎么配”,而在“怎么验”:EXPLAIN_REWRITE 的 MESSAGE 字段、V$SQL_PLAN 的 OBJECT_NAME 和 PARTITION_START、以及统计信息的 LAST_ANALYZED 时间戳——这三个点漏查任何一个,排查就会陷入循环。


















