普通视图:
物化视图:
跨数据库查询支持 | ✅ 支持 | ✅ 支持 | ✅ 支持(通过 FDW 扩展) | ||
ClickHouse 的物化视图是一种查询结果的持久化,它确实是给我们带来了查询效率的提升。用户查起来跟表没有区别,它就是一张表,它也像是一张时刻在预计算的表,创建的过程它是用了一个特殊引擎,加上后来 as select,就是 create 一个 table as select 的写法。
优点:
查询速度快,要是把物化视图这些规则全部写好,它比原数据查询快了很多,总的行数少了,因为都预计算好了。
缺点:
它的本质是一个流式数据的使用场景,是累加式的技术,所以要用历史数据做去重、去核这样的分析,在物化视图里面是不太好用的。在某些场景的使用也是有限的。而且如果一张表加了好多物化视图,在写这张表的时候,就会消耗很多机器的资源,比如数据带宽占满、存储一下子增加了很多。
2、语法
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]materialized_view_name
[TO [db.]target_table] -- 可选:指定目标表
[ENGINE = engine] -- 指定存储引擎
[POPULATE] -- 可选:是否填充现有数据
AS SELECT ... from -- 定义查询逻辑
参数说明:
materialized_view_name:物化视图的名称。
target_table(可选):物化视图的数据存储的目标表。如果未指定,ClickHouse 会自动创建一个隐式的目标表。
ENGINE:指定物化视图的存储引擎(如 MergeTree 系列)。
POPULATE(可选):是否将源表中已有的数据填充到物化视图中。如果启用,会立即将源表的数据插入到物化视图中。
AS SELECT ...:定义物化视图的查询逻辑。
3、创建物化视图的限制
必须指定物化视图的 engine 用于数据存储
TO [db].[table]语法的时候,不得使用 POPULATE
查询语句(select)可以包含下面的子句: DISTINCT, GROUP BY, ORDER BY, LIMIT…
物化视图的 alter 操作有些限制,操作起来不大方便
若物化视图的定义使用了 TO [db.]name 子语句,则可以将目标表的视图 卸载DETACH 再装载 ATTACH
4、物化视图的数据更新
物化视图创建好之后,若源表被写入新数据则物化视图也会同步更新
POPULATE 关键字决定了物化视图的更新策略:
1)若有 POPULATE 则在创建视图的过程会将源表已经存在的数据一并导入,类似于create table ... as
2)若无 POPULATE 则物化视图在创建之后没有数据,只会在创建后同步之后写入源表的数据
3)clickhouse 官方并不推荐使用 POPULATE,因为在创建物化视图的过程中同时写入的数据不能被插入物化视图。
物化视图不支持同步删除,若源表的数据不存在(删除了)则物化视图的数据仍然保留。
5、实际操作
示例一:基本用法
假设有一个表 source_table
,结构如下:
CREATE TABLE source_table (
event_date Date,
user_id UInt32,
amount Float64
) ENGINE = MergeTree()
ORDER BY (event_date, user_id);
amount
总和:
CREATE MATERIALIZED VIEW daily_amount_mv
ENGINE = SummingMergeTree()
ORDER BY (event_date, user_id)
AS SELECT
event_date,
user_id,
sum(amount) AS total_amount
FROM source_table
GROUP BY event_date, user_id;
当数据插入到
source_table
时,物化视图daily_amount_mv
会自动更新。数据存储引擎为
SummingMergeTree
,适合存储聚合数据。
CREATE TABLE target_table (
event_date Date,
user_id UInt32,
total_amount Float64
) ENGINE = SummingMergeTree()
ORDER BY (event_date, user_id);
CREATE MATERIALIZED VIEW daily_amount_mv
TO target_table
AS SELECT
event_date,
user_id,
sum(amount) AS total_amount
FROM source_table
GROUP BY event_date, user_id;
数据会存储到
target_table
中。物化视图
daily_amount_mv
只是一个逻辑视图,数据实际存储在target_table
中。
示例三:使用 POPULATE
如果源表 source_table
中已有数据,可以使用 POPULATE
将现有数据填充到物化视图中:
source_table
中已有数据,可以使用
POPULATE
将现有数据填充到物化视图中:
CREATE MATERIALIZED VIEW daily_amount_mv
ENGINE = SummingMergeTree()
ORDER BY (event_date, user_id)
POPULATE
AS SELECT
event_date,
user_id,
sum(amount) AS total_amount
FROM source_table
GROUP BY event_date, user_id;
POPULATE
会将source_table
中已有的数据插入到物化视图中。注意:
POPULATE
可能会导致数据重复,因此需要谨慎使用。
SELECT * FROM daily_amount_mv;
7、 删除物化视图
如果需要删除物化视图,可以使用以下命令:
DROP MATERIALIZED VIEW [IF EXISTS] [db.]materialized_view_name;
DROP MATERIALIZED VIEW IF EXISTS daily_amount_mv;
注意事项
1、数据一致性:
物化视图的数据是基于源表的数据生成的,因此源表的数据变更会触发物化视图的更新。
如果源表的数据被删除或更新,物化视图的数据不会自动同步(除非重新插入数据)。
2、性能:
物化视图会占用额外的存储空间,并增加数据插入时的计算开销。
适合用于预计算和存储聚合数据,以提高查询性能。
3、存储引擎:
物化视图的存储引擎通常选择
MergeTree
系列(如SummingMergeTree
、AggregatingMergeTree
等),以支持高效的聚合查询。4、POPULATE
的使用:使用
POPULATE
时,会立即将源表的数据插入到物化视图中,可能会导致数据重复或性能问题。
POPULATE
的使用。

