必须补全物化视图日志、主键约束和查询结构三要素才能在分区表上建FAST REFRESH物化视图;缺一即报ORA-12015或ORA-12052,且需确保日志含PRIMARY KEY、ROWID、SEQUENCE并覆盖所有SELECT列。

不能直接在分区表上建 FAST REFRESH 物化视图,除非你先补全物化视图日志、主键约束和查询结构三要素——漏掉任意一个,ORA-12015 或 ORA-12052 就会立刻报出来。
基表必须有主键且日志含 PRIMARY KEY + ROWID + SEQUENCE
分区表本身不自动提供 FAST 刷新所需的元数据。Oracle 不看“是不是分区”,只认日志里有没有 PRIMARY KEY 和 ROWID,以及 SEQUENCE 是否覆盖所有 SELECT 列。
- 先确认基表有主键:
ALTER TABLE your_part_table ADD CONSTRAINT pk_your_part_table PRIMARY KEY (id); - 再建日志,必须显式列出查询中涉及的所有列(包括 GROUP BY、WHERE、SELECT 中的):
CREATE MATERIALIZED VIEW LOG ON your_part_table WITH PRIMARY KEY, ROWID, SEQUENCE(id, dt, amt) INCLUDING NEW VALUES; - 如果基表是 INTERVAL 分区,日志仍建在主表名上,不用为每个分区单独操作
- 检查日志是否就绪:
SELECT SEQUENCE, PRIMARY_KEY, ROWID FROM USER_MVIEW_LOGS WHERE MASTER = 'YOUR_PART_TABLE';—— 三项都得是YES
物化视图定义里不能出现 VIEW、SYSDATE、子查询或聚合函数
哪怕只包了一层 CREATE VIEW v AS SELECT * FROM t,再用 SELECT * FROM v 建物化视图,REFRESH FAST 也会静默退化为 COMPLETE。Oracle 19c 不允许日志建在视图上。
- 必须展开逻辑,直接引用基表名:
SELECT t.id, t.dt, SUM(t.amt) FROM your_part_table t GROUP BY t.id, t.dt - 每个基表的
ROWID要加别名(多表连接时必需):t.ROWID t_rid, s.ROWID s_rid - 禁用非确定性函数:
SYSDATE、ROWNUM、DBMS_RANDOM.VALUE一出现,FAST 就被拒绝 - 外连接需特殊处理:不能用
LEFT JOIN语法,得用 UNION ALL 模拟,且每边都要有对应 ROWID 别名
TB 级分区表必须用 ON PREBUILT TABLE 分阶段加载
一次性 REFRESH COMPLETE 在超大分区表上极易锁表数小时甚至失败。FAST 刷新虽快,但首次构建仍要全量拉取,这步绕不开。
- 先建空目标表:
CREATE TABLE mv_target AS SELECT * FROM your_part_table WHERE 1=0; - 手动分区该表(比如按
dtRANGE 分区),并建好索引,否则后续查询无法剪枝 - 创建物化视图时绑定已有结构:
CREATE MATERIALIZED VIEW mv_target ON PREBUILT TABLE REFRESH FAST ON DEMAND AS SELECT ... - 首次填充用并行 INSERT:
INSERT /*+ APPEND PARALLEL(4) */ INTO mv_target SELECT ... FROM your_part_table;,再执行DBMS_MVIEW.REFRESH('mv_target', 'F')
并行刷新只在 atomic_refresh=FALSE 且会话启用 PARALLEL DML 时生效
很多人调了 parallelism => 8 却没提速,是因为根本没触发并行路径——FAST 刷新不走并行,COMPLETE 才走,且必须配对开关。
- 刷新前务必执行:
ALTER SESSION ENABLE PARALLEL DML;(不是 ALTER SYSTEM) - 调用刷新时显式关掉原子性:
DBMS_MVIEW.REFRESH('mv_target', method => 'F', atomic_refresh => FALSE, parallelism => 4); - 验证是否真并行:查
V$PX_SESSION,应看到多个Q00x进程;只看到 1 个说明没开成功 - 注意副作用:atomic_refresh=FALSE 下,刷新中途查询可能读到新旧混合数据,业务层要有容忍窗口
最容易被忽略的是:物化视图底层存储表(尤其是 ON PREBUILT TABLE 场景)必须手动分区,否则即使基表按时间分区,物化视图查询也扫全表——剪枝失效不是性能问题,是设计缺陷。











