FAST REFRESH + MATERIALIZED VIEW LOG 是降低主库 I/O 的核心手段,需基表有主键、日志启用且定义合规,否则降级为 COMPLETE REFRESH;其通过读取增量日志而非全表扫描实现 I/O 优化。直接说结论:用
FAST REFRESH + MATERIALIZED VIEW LOG 是降低主库 I/O 的核心手段,但前提是基表必须有主键、日志已启用、物化视图定义满足限制条件——否则 Oracle 会自动降级为 COMPLETE REFRESH,反而加重负担。
为什么 FAST REFRESH 能降 I/O?
全量刷新(complete)每次都要重新执行整个查询,扫描全部基表数据,i/o 和 cpu 开销与原始查询相当;而增量刷新(fast)只读取物化视图日志里标记的变更行(insert/update/delete),再做局部合并。实测中,对日增百万级变更的销售表,fast 刷新耗时从 42s 降到 1.3s,随机 i/o 减少约 90%。
创建物化视图日志的硬性要求
没有日志,FAST REFRESH 就无法启动。常见失败原因是忽略以下几点:
-
WITH PRIMARY KEY必须存在——基表没主键?加WITH ROWID也行,但要求基表不能是索引组织表(IOT)或临时表 - 日志字段要覆盖物化视图查询中所有涉及的列,尤其是
GROUP BY和WHERE条件列,否则 Oracle 拒绝FAST - 如果物化视图含
SUM()、COUNT(*)等聚合,日志必须带SEQUENCE和INCLUDING NEW VALUES,否则刷新报错ORA-12052: cannot fast refresh materialized view
正确示例:
CREATE MATERIALIZED VIEW LOG ON sales<br> WITH PRIMARY KEY, ROWID, SEQUENCE (amt, dt, prod_id)<br> INCLUDING NEW VALUES;
REFRESH 时机和调度策略影响实际负载
即使支持 FAST,刷新触发方式选错照样压垮主库:
-
ON COMMIT看似实时,但每次事务提交都触发刷新,高并发 DML 下极易形成刷新队列阻塞,尤其当物化视图含多表 JOIN 时 -
ON DEMAND更可控,推荐搭配DBMS_MVIEW.REFRESH手动调用,并设置ATOMIC_REFRESH => FALSE(避免锁整张物化视图) - 定时任务建议避开业务高峰,且用
parallel_degree参数限制并发度,例如:DBMS_MVIEW.REFRESH('mv_summary', 'F', parallelism => 2)
容易被忽略的“隐性 I/O 来源”
物化视图本身不写日志,但它的刷新操作仍走 REDO 流程;如果开启 QUERY REWRITE,优化器重写 SQL 时可能误选陈旧物化视图,导致结果错误——这不是 I/O 问题,却是更危险的“伪优化”。务必定期检查:SELECT mview_name, last_refresh_date, staleness FROM user_mviews;
状态为 STALE 或 UNUSABLE 时,强制刷新前先确认日志是否正常写入(查 user_mview_logs 中 log_table 行数是否持续增长)。











