物化视图查询重写不生效的主因是权限缺失、参数未启用或MV定义不合规;须确保用户直获QUERY REWRITE权限、QUERY_REWRITE_ENABLED=TRUE且MV含ENABLE QUERY REWRITE子句。
物化视图查询重写不生效的常见报错和现象
执行 select 时没走物化视图,执行计划里看不到 rewrite 相关操作;或者明明启用了 query_rewrite_enabled=true,但 explain plan 显示仍访问基表。最典型的错误提示是:ora-30397: one rewrite equivalence was not used,说明优化器尝试重写但失败了。
这不是“物化视图建错了”,而是重写路径被权限、配置或定义细节卡住了。Oracle 的查询重写非常保守——只要有一个环节不满足,就直接放弃,不会降级尝试。
必须检查的三个权限项
缺任意一项,QUERY REWRITE 都不会触发:
-
QUERY REWRITE系统权限(授予用户,不是角色):仅靠DBA角色不够,必须显式执行GRANT QUERY REWRITE TO username; -
GLOBAL QUERY REWRITE(如需跨 schema 重写):当物化视图和查询表不在同一 schema 时,需要这个额外权限 - 对物化视图本身的
SELECT权限:如果物化视图是别人建的,你得有SELECT ON schema.mv_name,不能只靠SELECT_CATALOG_ROLE
注意:QUERY REWRITE 权限无法通过角色继承,必须直授用户。用 SELECT * FROM SESSION_ROLES; 查不到它,得查 SESSION_PRIVS。
关键初始化参数与会话级设置
即使实例级开了,当前会话也可能关着:
- 实例参数
QUERY_REWRITE_ENABLED必须为TRUE或FORCE(FORCE会强制重写,哪怕代价更高) - 会话级要确认:
ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE;—— 某些应用连接池会重置会话参数 -
QUERY_REWRITE_INTEGRITY决定重写严格程度:ENFORCED(默认)要求 MV 有ENABLE QUERY REWRITE且约束/日志完备;TRUSTED允许无日志 MV;STALE_TOLERATED连 stale MV 都用。调试时可临时设为TRUSTED排查
改完参数后,记得重新 EXPLAIN PLAN,不要复用旧执行计划缓存。
MV 定义中容易被忽略的重写障碍
建 MV 时一个标点没写对,重写就静默失效:
- 建 MV 语句末尾必须带
ENABLE QUERY REWRITE,不能只写DISABLE QUERY REWRITE或漏掉 - 如果 MV 含聚合,必须有
GROUP BY且覆盖所有非聚合列;含DISTINCT的 MV 默认不支持重写,除非加ENABLE QUERY REWRITE且满足完整性约束 - 基表要有物化视图日志(
ON TABLE ... BUILD IMMEDIATE REFRESH FAST ON COMMIT类型尤其依赖),且日志里包含查询中涉及的所有列,包括ROWID和SEQUENCE - 查询中用到的函数必须是“可重写的”:比如
TO_CHAR(col, 'YYYY')可以,但TO_CHAR(col)(无格式)不行;自定义函数默认不可重写,除非显式声明DETERMINISTIC
重写失败往往不报错,只默默走原表。最稳的验证方式是:在会话里开 10053 事件,搜 trace 文件里的 query rewrite 和 failed 关键字。


















