首批通过分布式安全可靠测评,为关键业务系统打造
刷新物化视图
更新时间:2025-10-13 15:33:12
更新基表的数据可能会导致物化视图的数据与基表的数据不一致,为了维护物化视图的数据,OceanBase 数据库会通过刷新物化视图来实现。刷新物化视图也会自动更新其所有索引。
物化视图的刷新是串行执行的,通过加对象锁来实现。在物化视图刷新时,并不会对基表加锁,以提高并发性能。
刷新模式(刷新时机)
可以使用 ON DEMAND 子句指定物化视图在用户需要时进行刷新。
您可以通过使用 DBMS_MVIEW 包手动执行刷新操作,也可以在创建物化视图时设置 START WITH ... NEXT ... 来指定物化视图自动定时刷新。
更多有关 DBMS_MVIEW 的详细信息,参见 DBMS_MVIEW 概述。
刷新方法
全量刷新
刷新条件
当前基表的列与物化视图对应的列类型匹配,就符合全量刷新的条件。如果不匹配,将无法进行全量刷新。
刷新方式
OceanBase 数据库使用异地刷新的方式进行全量刷新,即创建一个隐藏表,在隐藏表上执行刷新语句,然后切换原表和隐藏表。因此,全量刷新操作需要额外的空间,并且会全量重建索引(如果有的话)。
说明
全量刷新可能是一个非常耗时的过程,尤其是在需要读取和处理大量数据的情况下。因此,在执行全量刷新之前,您应该始终考虑处理全量刷新所需的时间。
增量刷新
注意
- 由于
REFRESH FAST方法利用物化视图日志中的记录信息来确定需要增量刷新的内容,因此在使用增量刷新刷新物化视图时,需要在创建物化视图之前就创建基表的物化视图日志(mlog)。 - 增量刷新物化视图中使用的列都必须在 mlog 里。
单表增量刷新基本要求
不支持使用聚合函数
MAX和MIN进行增量更新。不支持内联视图、
UNION和子查询等复杂场景的增量更新。不支持包含不稳定输出值的表达式,如
ROWNUM和RAND等。不支持
ROLLUP和HAVING。不支持
ORDER BY。不支持窗口函数。
如果查询中包含
DISTINCT,那么可增量更新的物化视图中的输出列应该是唯一的,因此在这种情况下,可以直接禁止使用DISTINCT,或者将其移除。不带
GROUP BY的语句必须是标量聚合(Scalar Aggregate)。对于
GROUP BY场景的物化视图,仅支持SUM和COUNT等聚合函数,且聚合函数中只能使用简单的列。GROUP BY的要求如下:GROUP BY子句必须是标准的GROUP BY语法,不支持ROLLUP和HAVING。SELECT子句中必须包含所有的GROUP BY列。- 聚合函数不包含
DISTINCT关键字。 SELECT子句中必须包含COUNT(*),其它支持聚合函数及其它要求如下,目前暂不支持MIN和MAX函数。
聚合函数 SELECT 子句中必须包含依赖列 COUNT( expr ) N/A SUM ( expr ) COUNT( expr ) 或 expr 非 null AVG ( expr ) SUM ( expr ),COUNT( expr ) STDDEV ( expr ) SUM ( expr ),COUNT( expr ),SUM ( expr * expr ) VARIANCE ( expr ) SUM ( expr ),COUNT( expr ),SUM ( expr * expr ) 其它可拆分为 SUM 及 COUNT 的聚合函数... (计算方式变化,可能引起精度变化) SUM (col1),COUNT(col1)
多表简单连接增量刷新基本要求
FROM表必须为基表,不能为内联视图、视图和物化视图等。FROM表至少包含两张表,各表间仅存在内连接。FROM表均存在主键,且主键在SELECT中输出。FROM表均创建 mlog,且使视图中使用列均在 mlog 中存在。- 视图定义中不存在子查询。
- 视图定义中不存在
GROUP BY、ROLLUP、HAVING、WINDOW FUNCTION、DISTINCT、ORDER BY、LIMIT和FETCH等子句,为 SPJ 查询。 - 视图定义中不能使用
ROWNUM、RAND和SYSDATE等不稳定输出值的表达式。
增量刷新示例
创建表
test_tbl1。CREATE TABLE test_tbl1 (col1 INT PRIMARY KEY, col2 INT, col3 INT, col4 INT);在
test_tbl1表上创建物化视图日志。CREATE MATERIALIZED VIEW LOG ON test_tbl1 WITH SEQUENCE (col2, col3) INCLUDING NEW VALUES;创建刷新方法是增量刷新的物化视图。
创建名为
mv1_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中选择col2列,并计算count(*)、count(col3)和sum(col3)的聚合结果,分组依据是col2列的值。CREATE MATERIALIZED VIEW mv1_test_tbl1 REFRESH FAST ON DEMAND AS SELECT col2, count(*) cnt, count(col3) cnt_col3, sum(col3) sum_col3 FROM test_tbl1 GROUP BY col2;创建名为
mv2_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中计算count(*)、count(col3)和sum(col3)的聚合结果。CREATE MATERIALIZED VIEW mv2_test_tbl1 REFRESH FAST ON DEMAND AS SELECT count(*) cnt, count(col3) cnt_col3, sum(col3) sum_col3 FROM test_tbl1;创建名为
mv3_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中计算count(col3)和sum(col3)的结果。CREATE MATERIALIZED VIEW mv3_test_tbl1 REFRESH FAST ON DEMAND AS SELECT count(col3) cnt_col3, sum(col3) sum_col3 FROM test_tbl1;创建名为
mv4_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中选择col2和col3列,并计算count(*)、count(col3)和sum(col3)的聚合结果,以col2和col3作为分组依据。CREATE MATERIALIZED VIEW mv4_test_tbl1 REFRESH FAST ON DEMAND AS SELECT col2, col3, count(*) cnt, count(col3) cnt_col3, sum(col3) sum_col3 FROM test_tbl1 GROUP BY col2, col3;创建名为
mv5_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中选择col2列,并计算count(*)、count(col3)、sum(col3)、avg(col3)等聚合结果,同时还计算了一些自定义的列calcol1和calcol2,分组依据是col2列的值。CREATE MATERIALIZED VIEW mv5_test_tbl1 REFRESH FAST ON DEMAND AS SELECT col2, count(*) cnt, count(col3) cnt_col3, sum(col3) sum_col3, avg(col3) avg_col3, avg(col3) * sum(col3)/col2 calcol1, col2+sum(col3) calcol2 FROM test_tbl1 GROUP BY col2;创建名为
mv6_test_tbl1的物化视图。指定物化视图的刷新方法为增量刷新,并且可以根据需要手动触发刷新操作;物化视图的查询部分是从表test_tbl1中选择col2列,并计算count(*)、count(col3)、sum(col3)、count(col3*col3)、sum(col3*col3)和STDDEV(col3)的聚合结果,分组依据是col2列的值。CREATE MATERIALIZED VIEW mv6_test_tbl1 REFRESH FAST ON DEMAND AS SELECT col2, count(*) cnt, count(col3) cnt_col3, sum(col3) sum_col3, count(col3*col3) cnt_col3_2, sum(col3*col3) sum_col3_2, STDDEV(col3) stddev_col3 FROM test_tbl1 GROUP BY col2;
多表增量刷新示例
创建基表
t1和t2。CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT, c3 INT);CREATE TABLE t2(c1 INT PRIMARY KEY, c4 INT, c5 INT);在表
t1和表t2上创建物化视图日志。CREATE MATERIALIZED VIEW LOG ON t1 WITH PRIMARY KEY, ROWID, SEQUENCE (c2) INCLUDING NEW VALUES;CREATE MATERIALIZED VIEW LOG ON t2 WITH PRIMARY KEY, ROWID, SEQUENCE (c4) INCLUDING NEW VALUES;创建表
t1和表t2连接的增量刷新的物化视图mv1_t1_t2。CREATE MATERIALIZED VIEW mv1_t1_t2 REFRESH FAST AS SELECT t1.c1 t1c1, t1.c2, t2.c1 t2c1, t2.c4 FROM t1 JOIN t2 ON t1.c1=t2.c1;
说明
- 为了使简单连接物化视图在增量刷新和实时物化视图中获得较好的性能,推荐按照以下方式为物化视图及其依赖基表创建索引:
- 为每张表的连接键创建索引,用于提升增量更新和实时物化视图中表的连接性能。
- 为物化视图中各基表主键列创建索引。
- 随着物化视图中
JOIN表数量的增加,物化视图的增量刷新性能和实时物化视图查询性能通常会有所下降。
为物化视图及其依赖基表创建索引示例如下:
(可选)使用以下语句删除相关测试数据。
如果没有以下数据库对象可以跳过此步骤。
DROP MATERIALIZED VIEW LOG ON t1; DROP TABLE IF EXISTS t1; DROP MATERIALIZED VIEW LOG ON t2; DROP TABLE IF EXISTS t2; DROP MATERIALIZED VIEW rt_mv1;使用以下语句创建表
t1和索引idx_t1_c2。CREATE TABLE t1(c1 INT PRIMARY KEY AUTO_INCREMENT, c2 INT, c3 INT, c4 INT, c5 INT); CREATE INDEX idx_t1_c2 ON t1(c2);使用以下语句创建表
t2和索引idx_t2_c3。CREATE TABLE t2(c1 INT PRIMARY KEY AUTO_INCREMENT, c2 INT, c3 INT, c4 INT, c5 INT); CREATE INDEX idx_t2_c3 ON t2(c3);使用以下语句在
t1和t2表上分别创建物化视图日志。CREATE MATERIALIZED VIEW LOG ON t1 WITH PRIMARY KEY, ROWID, SEQUENCE (c2, c3, c4) INCLUDING NEW VALUES; CREATE MATERIALIZED VIEW LOG ON t2 WITH PRIMARY KEY, ROWID, SEQUENCE (c2, c3, c4) INCLUDING NEW VALUES;使用以下语句创建实时物化视图
rt_mv1。CREATE MATERIALIZED VIEW rt_mv1 NEVER REFRESH ENABLE ON QUERY COMPUTATION DISABLE QUERY REWRITE AS SELECT t1.c1 AS t1_c1, t2.c1 AS t2_c1, t1.c2 AS t1_c2, t2.c2 AS t2_c2, t1.c3 AS t1_c3, t2.c3 AS t2_c3 FROM t1, t2 WHERE t1.c2 = t2.c3;使用以下语句为物化视图中各基表主键列创建索引。
CREATE INDEX idx_mv_t1_c1 ON rt_mv1(t1_c1); CREATE INDEX idx_mv_t2_c1 ON rt_mv1(t2_c1);
手动刷新物化视图
当物化视图的刷新模式是 ON DEMAND,可以使用 DBMS_MVIEW 包进行手动刷新。
说明
物化视图的所有者和租户管理员用户才可以执行刷新操作。
使用 REFRESH 刷新物化视图
DBMS_MVIEW.REFRESH (
IN mv_name VARCHAR(65535), -- 物化视图名称
IN method VARCHAR(65535) DEFAULT NULL, -- 刷新选项
-- f 快速刷新
-- ? 强制刷新
-- C|c 完全刷新
-- A|a 始终刷新,等价于C
IN refresh_parallel INT DEFAULT 1); -- 刷新并行度
示例如下:
向表
test_tbl1中插入3条数据。INSERT INTO test_tbl1 VALUES (1, 1, 1, 1),(2, 2, 2, 2),(3, 3, 3, 3);查看物化视图
mv1_test_tbl1信息。SELECT * FROM mv1_test_tbl1;返回结果如下:
Empty set使用
DBMS_MVIEW.REFRESH手动刷新物化视图mv1_test_tbl1。CALL DBMS_MVIEW.REFRESH('mv1_test_tbl1');再次查看物化视图
mv1_test_tbl1信息。SELECT * FROM mv1_test_tbl1;返回结果如下:
+------+------+----------+----------+ | col2 | cnt | cnt_col3 | sum_col3 | +------+------+----------+----------+ | 1 | 1 | 1 | 1 | | 2 | 1 | 1 | 2 | | 3 | 1 | 1 | 3 | +------+------+----------+----------+ 3 rows in set
刷新并行度
可以通过指定 refresh_parallel 设置本次刷新的并行度,目前只影响全量刷新,增量刷新不受此参数影响。
示例如下:
指定并行度刷新物化视图。
CALL DBMS_MVIEW.REFRESH('mv1_test_tbl1', refresh_parallel => 8);
自动刷新物化视图
创建物化视图的时候,如果指定了START WITH datetime_expr 和 NEXT datetime_expr 子句,会为物化视图创建一个后台自动刷新任务。
刷新并行度
在后台自动刷新物化视图时,可以通过以下三种方式来指定并行度:
说明
- 下述并行度优先级依次降低。
- 刷新并行度目前只对全量刷新有影响,增量刷新不受影响。
- 下述示例 SQL 仅作为演示并行度使用方法的参考,并不能执行。
在 Hint 中指定并行度。
示例如下:
CREATE /*+ parallel(8) */ MATERIALIZED VIEW ...在 DDL 的 Session 变量中指定并行度。
示例如下:
启用 DDL 并行度。
系统级别:
SET _ENABLE_PARALLEL_DDL = 1;Session 级别:
SET SESSION _ENABLE_PARALLEL_DDL = 1;设置 DDL 并行度值
系统级别:
SET _FORCE_PARALLEL_DDL_DOP = 8;Session 级别:
SET SESSION _FORCE_PARALLEL_DDL_DOP = 8;
创建物化视图时指定并行度(Table DOP)。
示例如下:
CREATE MATERIALIZED VIEW xxx PARALLEL 8 ...
物化视图刷新统计信息
OceanBase 系统能够收集并保存物化视图刷新操作的相关统计信息,这些信息可通过特定的视图进行查询。当前和历史物化视图刷新操作的统计信息存储在数据库中。通过历史物化视图刷新统计信息,您可以了解和分析数据库中物化视图刷新性能。
物化视图刷新的统计信息作用如下:
报告功能:提供物化视图刷新操作的当前及历史统计概览,包括刷新执行所需的实际时间,以便跟踪和监控刷新性能。
诊断功能:通过详尽的当前和历史统计数据,能够有效地分析物化视图刷新的性能。例如,若物化视图的刷新耗时较长,统计数据可以帮助识别是系统负载增加还是因数据变更量增大导致的性能下降。
物化视图收集统计信息
物化视图收集统计信息。可以通过 analyze table 或者 call dbms_stats.gather_table_stats('database_name', 'table_name') 来收集统计信息。
更多有关收集表和列的统计信息的信息,请参见 GATHER_TABLE_STATS。
更多有关管理物化视图刷新操作的统计信息的收集和保留的信息,请参见 DBMS_MVIEW_STATS 概述。
展示物化视图刷新信息
| 视图名 | 功能描述 |
|---|---|
| DBA_MVIEWS | 展示物化视图信息。 |
| DBA_MVREF_STATS_SYS_DEFAULTS | 物化视图刷新历史统计属性的系统范围默认值。 |
| DBA_MVREF_STATS_PARAMS | 展示与每个物化视图关联的刷新统计信息属性。 |
| DBA_MVREF_RUN_STATS | 展示物化视图的每次刷新运行的信息,每次运行均由 REFRESH_ID 标识。 |
| DBA_MVREF_STATS | 展示物化视图刷新的基本计时统计信息。 |
| DBA_MVREF_CHANGE_STATS | 展示物化视图刷新相关的统计信息。 |
| DBA_MVREF_STMT_STATS | 展示刷新语句关联的信息。 |