增量刷新物化视图(Incremental Materialized View,IVM)是物化视图的高级形态。相较于全量刷新需要每次重新计算整个查询,增量刷新仅根据基表的数据变更(INSERT、UPDATE、DELETE),准实时地更新视图中的差异部分,从而大幅降低系统负载并提升数据的实时性。
工作原理
增量刷新物化视图的核心思路是:只处理变化的部分,而不是每次重新计算全部数据。
当基表发生INSERT、UPDATE、DELETE操作时,系统会自动记录这些变更。执行增量刷新时,仅将这些变更合并到物化视图中。整个过程在IMCI列存节点上高效执行,无需Binlog与触发器,对基表无锁定影响。
FAST(增量刷新):仅处理自上次刷新以来的变更数据,速度快、开销低。
COMPLETE(全量刷新):重新计算整个查询,适合首次初始化或数据修复。
适用范围
使用增量刷新物化视图需满足以下条件:
集群:PolarDB MySQL版集群需满足以下条件:
MySQL 8.0.2,内核小版本需为8.0.2.2.35及以上。
列存索引(IMCI)参数:
参数名
默认值
要求值
说明
imci_enable_window_function
2
>= 2
需开启支持IMCI窗口函数。
imci_enable_nci_async_pre_commit
OFF
OFF
需关闭NCI异步预提交,避免影响增量数据一致性。
说明当前参数默认为OFF,且暂不支持调整。
imci_enable_hybrid_plan
ON
OFF
需关闭混合执行计划,确保增量刷新在列存索引只读节点执行。
说明您可以通过PolarDB控制台修改以上参数。
核心优势
优势 | 说明 |
低延迟数据同步 | 仅处理增量变化,避免全量扫描基表,使视图数据以极低延迟与基表保持同步,刷新时间从分钟级降至秒级甚至毫秒级。 |
降低系统负载 | 大幅减少CPU、内存和I/O资源消耗,在基表数据量巨大而变更量相对较小的场景下效果尤为显著。 |
无缝利用IMCI列存 | 增量计算在IMCI列存节点执行,充分利用列存的高速聚合能力。 |
加速分析查询 | 在HTAP(混合事务/分析处理)场景下,为复杂的聚合、连接查询提供毫秒级的响应能力。 |
自动后台维护 | 系统自动管理增量日志(Delta表)的生命周期,无需手动干预。 |
应用场景
预计算分析:复杂多表关联的宽表化预处理,避免每次查询重复执行代价高昂的关联操作。
报表加速:为实时数仓或BI报表提供预计算数据,通过增量刷新将每次更新开销降低90%以上。
计算复用:通过嵌套物化视图实现计算复用。
实时数仓:近实时反映基表数据变化的分析型查询。
HTAP混合负载:将频繁更新的OLTP数据以低延迟同步到分析视图,实现TP/AP负载分离。
使用限制
通用限制:
不支持的语法:子查询、
UNION、ORDER BY、LIMIT、窗口函数、HAVING、ROLLUP、CTE均不支持增量刷新。UNION ALL:暂不支持。基表要求:
基表需开启列存索引IMCI(
polar_enable_imci = ON),且基表所有列均已被IMCI覆盖。基表不能是普通视图,也不能是非增量刷新的物化视图(允许嵌套物化视图,但内层物化视图需要是也是增量刷新视图)。
存储开销:
物化视图会存储数据副本,会占用额外的存储空间。
系统为维护增量物化视图刷新变更,也会占用额外的存储空间,但不会一直增长,会定期回收无效数据。
单表过滤场景限制:
基表需有显式主键。
不支持
DISTINCT。
单表聚合场景限制:
基表需有显式主键。
GROUP BY列需使用表的单列,不支持表达式(如GROUP BY YEAR(create_time)不支持,需改为GROUP BY create_year)。支持的聚合函数:
COUNT、SUM、AVG。暂不支持的聚合函数:
STDDEV、VARIANCE、MIN、MAX。暂不支持无
GROUP BY列的聚集。暂不支持多表聚合。
多表连接场景限制
所有基表需包含显式主键。
不支持
RIGHT JOIN。连接顺序需为左深树形式,不可出现
A JOIN (B LEFT JOIN C) JOIN D的嵌套结构。每个表的ON条件需至少包含另一个表的列,不允许出现形如
A JOIN B ON B.id = 1的语法。
语法说明
CREATE MATERIALIZED VIEW mv_name
[REFRESH [COMPLETE | FAST] [ON DEMAND]]
[START WITH now()] [NEXT now() + interval 5 second]
AS SELECT ... FROM base_table;FAST:指定为增量刷新模式,仅处理基表增量变更。COMPLETE:全量刷新模式,每次重新计算整个查询。ON DEMAND:按需刷新,需手动触发或利用后台定义的刷新间隔进行刷新。
操作示例
示例一:单表过滤(FILTER类型)
创建基表(需开启列存索引)。
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, c3 INT) COMMENT 'COLUMNAR=1'; INSERT INTO t1 VALUES (1, 1, 1);创建增量物化视图。
CREATE MATERIALIZED VIEW mv_filter REFRESH FAST ON DEMAND AS SELECT * FROM t1 WHERE c2 < 5;执行全量刷新(首次建立初始数据)。
REFRESH MATERIALIZED VIEW mv_filter;基表数据变更后执行增量刷新。
-- 基表变更 INSERT INTO t1 VALUES (2, 2, 3); DELETE FROM t1 WHERE c1 = 1; -- 增量刷新(仅处理上述变更) REFRESH MATERIALIZED VIEW mv_filter;
示例二:聚合统计(AGGREGATE类型)
-- 创建基表(需开启列存索引)
CREATE TABLE orders (
order_id INT PRIMARY KEY, -- 订单唯一ID(主键)
user_id INT NOT NULL, -- 用户ID(GROUP BY 列)
amount DECIMAL(12, 2) NOT NULL, -- 订单金额(聚合计算列)
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 订单时间(常规业务字段)
)COMMENT 'COLUMNAR=1';
-- 聚合统计
CREATE MATERIALIZED VIEW mv_user_order_stats
REFRESH FAST ON DEMAND
AS SELECT
user_id,
COUNT(*) AS order_count,
SUM(amount * 2) AS total_amount,
AVG(CAST(amount AS INT)) AS avg_amount
FROM orders
GROUP BY user_id;支持的聚合函数:COUNT(*)、COUNT(expr)、SUM(expr)、AVG(expr)。
示例三:多表INNER JOIN
创建基表。
CREATE TABLE t4 (id4 INT PRIMARY KEY, c2 INT, c3 VARCHAR(50)) COMMENT 'COLUMNAR=1'; CREATE TABLE t5 (id5 INT PRIMARY KEY, c2 INT, c3 VARCHAR(50)) COMMENT 'COLUMNAR=1'; CREATE TABLE t6 (id6 INT PRIMARY KEY, c2 INT, c3 VARCHAR(50)) COMMENT 'COLUMNAR=1'; INSERT INTO t4 VALUES (1, 10, 'A'), (2, 20, 'B'), (3, 30, 'C'); INSERT INTO t5 VALUES (1, 100, 'X'), (2, 200, 'Y'), (4, 400, 'Z'); INSERT INTO t6 VALUES (1, 1000, 'P'), (2, 2000, 'Q'), (3, 3000, 'R');创建多表INNER JOIN增量物化视图。
CREATE MATERIALIZED VIEW mv_inner_with_where_on REFRESH FAST ON DEMAND AS SELECT t4.id4, t4.c2, t5.id5, t5.c2 AS t5_c2, t6.id6, t6.c2 AS t6_c2 FROM t4 INNER JOIN t5 ON t4.id4 = t5.id5 INNER JOIN t6 ON t4.id4 = t6.id6 WHERE t4.c2 > 5 AND t5.c2 > 50;执行全量刷新并验证。
-- 全量刷新(首次建立初始数据) REFRESH MATERIALIZED VIEW mv_inner_with_where_on; -- 基表变更 INSERT INTO t4 VALUES (4, 40, 'D'); INSERT INTO t6 VALUES (4, 4000, 'S'); UPDATE t4 SET c2 = 15 WHERE id4 = 1; DELETE FROM t5 WHERE id5 = 4; INSERT INTO t5 VALUES (5, 400, 'W'); -- 增量刷新 REFRESH MATERIALIZED VIEW mv_inner_with_where_on;
示例四:LEFT JOIN
-- 创建基表(需开启列存索引)
-- 创建产品表(被关联表 / 右表)
CREATE TABLE products (
product_id INT PRIMARY KEY, -- 关联键,必须是主键
product_name VARCHAR(100) NOT NULL, -- 产品名称
price DECIMAL(10, 2) -- 其他业务字段
) COMMENT 'COLUMNAR=1';
-- 创建订单明细表(主表 / 左表)
CREATE TABLE order_items (
item_id INT PRIMARY KEY, -- 明细ID,必须是主键
order_id INT NOT NULL, -- 订单ID
product_id INT, -- 关联键,允许为NULL(因为是LEFT JOIN)
quantity INT NOT NULL, -- 购买数量
FOREIGN KEY (product_id) REFERENCES products(product_id) -- 保持外键约束(可选)
) COMMENT 'COLUMNAR=1';
-- LEFT JOIN
CREATE MATERIALIZED VIEW mv_order_with_product
REFRESH FAST ON DEMAND
AS SELECT
oi.item_id,
oi.order_id,
p.product_name,
oi.quantity
FROM order_items oi
LEFT JOIN products p ON oi.product_id = p.product_id;示例五:嵌套物化视图(计算复用)
嵌套物化视图是指在一个增量刷新物化视图之上再创建另一个增量刷新物化视图,实现计算结果的逐层复用。例如先从基表过滤出有效数据,再对过滤结果做聚合统计,刷新时每层仅处理各自的增量变更。
创建基表。
CREATE TABLE order_log ( order_id INT PRIMARY KEY, user_id INT, product_category VARCHAR(50), amount DECIMAL(10,2), status VARCHAR(20), created_year INT ) COMMENT 'COLUMNAR=1'; INSERT INTO order_log VALUES (1, 101, 'electronics', 299.00, 'paid', 2025), (2, 102, 'clothing', 59.90, 'paid', 2025), (3, 103, 'electronics', 499.00, 'cancelled', 2025), (4, 101, 'clothing', 120.00, 'paid', 2025), (5, 104, 'electronics', 89.00, 'paid', 2025);创建第一层增量物化视图:过滤出已支付订单。
CREATE MATERIALIZED VIEW mv_paid_orders REFRESH FAST ON DEMAND AS SELECT order_id, user_id, product_category, amount, created_year FROM order_log WHERE status = 'paid';执行全量刷新建立初始数据。
REFRESH MATERIALIZED VIEW mv_paid_orders;创建第二层增量物化视图:基于第一层视图按品类聚合统计。
CREATE MATERIALIZED VIEW mv_category_revenue REFRESH FAST ON DEMAND AS SELECT product_category, COUNT(*) AS order_count, SUM(amount) AS total_revenue FROM mv_paid_orders GROUP BY product_category;执行全量刷新建立初始数据。
REFRESH MATERIALIZED VIEW mv_category_revenue;基表数据变更后,按层级依次执行增量刷新。
-- 基表新增数据 INSERT INTO order_log VALUES (6, 105, 'electronics', 199.00, 'paid', 2025), (7, 106, 'clothing', 75.00, 'cancelled', 2025); -- 按依赖顺序依次刷新:先刷新第一层,再刷新第二层 REFRESH MATERIALIZED VIEW mv_paid_orders; REFRESH MATERIALIZED VIEW mv_category_revenue; -- 验证结果:order_id=7 因 status='cancelled' 被第一层过滤,不会进入第二层统计 SELECT * FROM mv_category_revenue;
嵌套物化视图需按依赖顺序从底层到顶层依次刷新,确保每层数据一致。第一层物化视图必须是增量刷新类型(REFRESH FAST)。
执行增量刷新
手动触发刷新:
REFRESH MATERIALIZED VIEW mv_name;增量刷新仅处理自上次刷新以来基表发生的变更,无需扫描全表,速度快、开销低。
首次执行REFRESH MATERIALIZED VIEW时,系统会自动完成全量刷新以建立初始数据,之后的刷新均为增量刷新。
删除物化视图
DROP MATERIALIZED VIEW mv_name;删除物化视图后,如果参数delta_mv_auto_cleanup = ON(默认),系统会自动清理对应的Delta表。
管理与监控
查看物化视图列表
SELECT
table_name,
table_schema,
base_tables
first_refresh_time,
refresh_strategy,
last_start_time,
last_end_time
FROM mysql.view_materialized_info
WHERE refresh_strategy = 'FAST';查看所有物化视图
SELECT * FROM mysql.view_materialized_info;监控刷新任务队列
SELECT * FROM information_schema.materialized_view_refresh_queue;常见问题
如何确认物化视图是否在进行增量刷新?
通过以下语句查看refresh_strategy列是否为FAST,并通过last_refresh_status确认最近一次刷新结果:
SELECT table_name, refresh_strategy, last_start_time, last_end_time
FROM mysql.view_materialized_info;基表数据变更后,物化视图何时更新?
物化视图采用按需刷新(ON DEMAND)模式,需要手动执行REFRESH MATERIALIZED VIEW mv_name触发刷新。刷新前,视图数据反映的是上次刷新时的状态。
增量刷新期间基表是否会被锁定?
不会。增量刷新期间您可以继续对基表进行正常读写,不受影响。
单表聚合和多表聚合是否支持增量刷新?
单表聚合当前已支持增量刷新。多表聚合和UNION ALL暂不支持。
增量刷新最短刷新周期是多少?
目前最短刷新周期为1秒。