注册
DM8物化视图
专栏/技术分享/ 文章详情 /

DM8物化视图

未来的嫑嫑 2026/10/10 202 0 0
摘要

物化视图是什么:
我的理解是:普通视图保存的是一条 SQL,物化视图保存的是这条 SQL 的查询结果—— 结果以物理表的形式落盘,所以它“像一张表”。

一、物化视图与普通视图区别

image.png
简单说:视图是 “查询的快捷方式”,物化视图是 “查询结果的快照”,本质是用空间换时间—— 多占一点磁盘,换高频查询的大幅提速。

二、刷新方式:快速、完全、强制

物化视图的数据不会自己更新,需要 “刷新” 来和基表同步。刷新方式可以从两个维度理解:
按刷新方法:

  • 快速刷新(FAST):借助物化视图日志,只同步上次刷新以来的增量数据。适合基表变更频繁、又希望尽量近实时同步的场景。但它的前提是物化视图的 SQL 结构足够简单(见第七节第 1 点)。
  • 完全刷新(COMPLETE):先清空旧数据,再全量重建。适合基表数据量不大,或允许夜间批量刷新的场景。
  • 强制刷新(FORCE):先尝试快速刷新,条件不满足就自动降级为完全刷新。省心,但效率取决于能否走快速路径。

按触发时机:

  • 按需刷新(ON DEMAND):不自动刷新,需要时手动执行 REFRESH。适合数据变化不频繁、实时性要求不高的场景。
  • 定时刷新(START WITH / NEXT):START WITH 指定首次刷新时间,NEXT 指定刷新间隔,比如 “每天凌晨 1 点刷一次”。
  • 提交时刷新(ON COMMIT):基表有事务提交时立即刷新,实时性最好,但对频繁更新的表代价很高,生产环境慎用。

三、语法骨架


CREATE MATERIALIZED VIEW [模式名.]物化视图名
(
    -- 可选:指定列名(不指定则自动继承查询中的列名)
    列1, 列2, ...
)
-- ========== 存储选项(物理属性) ==========
[STORAGE (INITIAL 初始大小, NEXT 增长大小, MINEXTENTS 最小区数, ...)]
[USING INDEX STORAGE (索引存储参数)]
[USING INDEX PCTFREE 百分比]
[PARTITION BY 分区方式 (分区列)]  -- 支持对物化视图分区

-- ========== 刷新方式(重点) ==========
[REFRESH 
    { FAST | COMPLETE | FORCE }   -- 刷新方式:快速/完全/强制
    [ ON { DEMAND | COMMIT } ]    -- 触发时机:按需/提交时
    [ START WITH 开始时间 ]       -- 首次自动刷新时间
    [ NEXT 下次刷新时间表达式 ]   -- 刷新间隔
    [ WITH { PRIMARY KEY | ROWID } ]  -- 刷新依据
]

-- ========== 是否预建表 ==========
[BUILD { IMMEDIATE | DEFERRED }] 
 -- IMMEDIATE(立即创建数据)/ DEFERRED(只建结构,稍后刷新)

-- ========== 查询语句 ==========
ASSELECT ... FROM ... [GROUP BY ...] [HAVING ...]

四、实验:从建日志到删除

以下实验都在测试库 TEST 下完成,基表是订单明细表 ORDER_DETAIL,字段为:ORDER_DATE(下单日期)、ORDER_NO(订单号)、AMOUNT(金额)、QTY(数量)。目标是建一个 “每日订单汇总” 物化视图,每天自动刷新一次。
1、创建物化视图日志表
快速刷新靠物化视图日志(MLOG)记录基表增量,所以先建日志:

CREATE MATERIALIZED VIEW LOG ON TEST.ORDER_DETAIL
STORAGE (INITIAL 1, NEXT 1, MINEXTENTS 1, FILLFACTOR 0)
WITH ROWID, PRIMARY KEY;

2、创建物化视图
– 每天刷新一次:统计每日订单数、总金额、总件数

CREATE MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY
REFRESH COMPLETE ON DEMAND
START WITH SYSDATE
NEXT SYSDATE + INTERVAL '1' DAY
AS SELECT
    ORDER_DATE,
    COUNT(*)     AS ORDER_COUNT,
    SUM(AMOUNT)  AS TOTAL_AMOUNT,
    SUM(QTY)     AS TOTAL_QTY
FROM TEST.ORDER_DETAIL
GROUP BY ORDER_DATE;

3、手动刷新

-- 全量重建
REFRESH MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY COMPLETE;
-- 增量同步(前提:满足快速刷新约束)
REFRESH MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY FAST;
-- 强制刷新:先试 FAST,不行自动降级为 COMPLETE
REFRESH MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY FORCE;

4、修改刷新计划、删除

-- 修改刷新时间(改为每小时刷新)
ALTER MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY
REFRESH COMPLETE ON DEMAND
START WITH SYSDATE
NEXT SYSDATE + INTERVAL '1' HOUR;
-- 不再需要时删除
DROP MATERIALIZED VIEW TEST.MV_ORDER_DAY_SUMMARY;

五、应用场景

image.png
判断标准就一条:结果集是 “算一遍、读很多遍”,就值得物化;如果是 “每次查的数据都不一样”,用了反而浪费空间。

六、物化视图的索引优化

物化视图可以像普通表一样建索引,这是它比普通视图强的地方:

-- 在物化视图上建索引(大幅提升查询速度)
CREATE INDEX IDX_MV_DAILY_SALES_SALE_DATE ON DEMO.MV_DAILY_SALES(SALE_DATE);
CREATE BITMAP INDEX IDX_MV_DAILY_SALES _ORDER_COUNT ON DEMO. MV_DAILY_SALES (ORDER_COUNT);

七、注意事项

1. 快速刷新不是所有SQL都支持
官方文档按 SQL 结构把物化视图分成 AGGREGATE(仅分组聚合)、JOIN(仅多表连接)、SUBQUERY(仅子查询)、COMPLEX(其他复杂类型)四类。带 DISTINCT、UNION、外连接等复杂操作的,快速刷新会失败,只能退回 FORCE 或 COMPLETE。设计 SQL 时就要想好刷新策略。
2. 物化视图日志大小要注意,要定期清理
日志会不断累积基表的变更记录,越来越大,影响基表 DML 性能。定期执行:

PURGE MATERIALIZED VIEW LOG ON TEST.ORDER_DETAIL;

3. COMPLETE 刷新会锁基表
完全刷新期间基表会被锁定,业务 DML 会被阻塞。生产环境放业务低峰期执行,或者改用快速刷新。
4. 用数据字典监控刷新状态
刷新失败不会主动报警,数据陈旧了很难发现。查 SYS.USER_MVIEWS 可以看每个物化视图的状态:

SELECT MVIEW_NAME, MVIEW_TYPE, LAST_REFRESH_DATE, STALENESS
FROM USER_MVIEWS;

LAST_REFRESH_DATE 停在好几天前,说明刷新任务已经挂了,要赶紧查刷新任务的报错。

八、总结

物化视图是 DM8 里 “以空间换时间” 的典型工具:把高频聚合计算前置,换取查询性能的提升。它不复杂,但刷新策略的选择、日志的维护、状态的监控这三件事没做好,优化工具也可能变成新的麻烦。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服