query_rewrite_integrity控制重写数据可信度校验级别,默认enforced要求mv必须fresh、基表有主键和完整日志、约束启用等,任一不满足即静默跳过重写;trusted可跳过部分校验用于调试,stale_tolerated则连stale mv也敢用但风险极高。
物化视图查询重写失效,大概率不是没开开关,而是 query_rewrite_integrity 参数卡住了——它默认值 enforced 会让 oracle 在 mv 稍有陈旧、日志缺失或约束不全时直接放弃重写,连试都不试。
QUERY_REWRITE_INTEGRITY 是什么,为什么它比 QUERY_REWRITE_ENABLED 更关键
这个参数不控制“是否启用重写”,而是控制“在什么数据可信度下才敢重写”。Oracle 的重写引擎极其保守:哪怕其他条件全满足,只要 QUERY_REWRITE_INTEGRITY 的校验通不过,就静默跳过,执行计划里连 hint 都不认。
-
ENFORCED(默认):要求 MV 必须是FRESH、基表有主键/物化视图日志、所有约束启用、无DISABLE ON QUERY COMPUTATION。任意一项不满足,EXPLAIN PLAN就显示访问基表 -
TRUSTED:跳过 STALENESS 检查和部分日志/约束验证,假设 DBA 手动保证刷新及时、数据可信。调试时最常用 -
STALE_TOLERATED:连STALE状态的 MV 都敢用,风险最高,仅限离线报表等容忍脏读场景
怎么快速验证是不是它导致失效
别猜,直接改会话级参数 + 查 DBMS_MVIEW.EXPLAIN_REWRITE 输出:
- 先执行
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED; - 再跑
EXPLAIN PLAN FOR SELECT ...,看执行计划是否切到 MV - 如果切了,说明原因为
ENFORCED下的某项校验失败;此时立刻执行DBMS_MVIEW.EXPLAIN_REWRITE('your_query', 'MV_NAME') - 查
MV_CAPABILITIES_TABLE中MSGTXT字段,常见提示如:QSM-01150: no suitable materialized view found或materialized view is stale
ENFORCED 模式下容易被忽略的校验点
它不只看 MV 是否 FRESH,还深挖底层支撑是否完备:
- 基表没建物化视图日志,或日志缺
INCLUDING NEW VALUES→ 即使 MV 定义含ENABLE QUERY REWRITE,也会被拒 - MV 含聚合但没
GROUP BY所有非聚合列 →EXPLAIN_REWRITE返回QSM-01102: query rewrite not supported - 查询中用了
TO_CHAR(dt, 'YYYY-MM'),而 MV 存的是原始DATE列 → 表达式不可重写,ENFORCED直接拦截 - 分区键列名大小写不一致(比如基表用
"EVENT_TIME",MV 分区定义用event_time)→ Oracle 认为语义不等价
生产环境调参要注意什么
TRUSTED 不是万能解药,它绕过的是 Oracle 的自动校验,不是数据本身的一致性:
- 切到
TRUSTED后重写生效,但若 MV 实际是STALE,查询结果就是错的——必须同步盯紧REFRESH任务是否真在跑 - 不能只改会话级,应用连接池(如 Druid)初始化 SQL 里没加
ALTER SESSION,上线后照样回退到ENFORCED -
STALE_TOLERATED在 OLTP 场景极危险:一个未提交的事务就能让 MV 内容与基表偏差数小时,且无任何报错提示
真正要治本,得顺着 EXPLAIN_REWRITE 的 MSGTXT 去修日志、补约束、调刷新策略,而不是长期依赖参数降级。参数只是诊断杠杆,不是生产兜底方案。











