clickhouse的物化视图是一种查询结果的持久化,给我们带来了查询效率的提升。用户查询效果和查表没有区别,其本质就是一张表,一张时刻在预计算的表,创建的过程用了一个特殊引擎:
注:使用create语法,会创建一个隐藏的目标来保存视图数据,使用To表名,保存到一张显示的表,没有加To表名,表名默认就是.inner.物化视图名,
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT …
“查询结果集”的范围很广泛,可以是基础表中部分数据的一份简单拷贝,也可以是多表join之后产生的结果或其子集、或者原始数据的聚合指标等等。所以,物化视图不会随着基础表的变化而变化,所以也称为快照
创建物化视图的限制:
1、必须指定物化视图的engine用于数据存储
2、使用To[db].[table]语法时,不得使用POPULATE,POPULATE会将历史数据全都加载转换过来,数据量大时存在一个不可用时间(官方并不推荐在创建物化视图的时候使用POPULATE,因为在创建物化视图过程中同时写入的数据不能被插入物化视图)
3、查询语句(select)可以包含下面的句子:DISTINCT、GROUP BY、LIMIT等
4、若物化视图的定义使用了 TO [db.]name 子语句,则可以将目标表的视图卸载DETACH 再装载 ATTACH
普通视图不保存数据,保存的仅仅是查询语句,查询的时候还是从原表中读取数据,可以将普通视图理解为是个子查询。
物化视图则是 把查询的结果根据相应的引擎存入到磁盘或者内存中,对数据重新进行了组织,生成了一张新表
优缺点:
优点:查询速度快,提前将物化视图规则写好,比直接查询原数据了很多 (物化视图起到了一个同步的作用)
缺点:本质是流式数据 的使用场景,采用累加式的技术,要用到历史数据做去重、去核这样的分析。使用场景有限,如果一张表加了很多物化视图,在写这张表的时候会消耗很多及其的资源,比如数据带宽占满,存储量突增
- #创建表
- CREATE TABLE `ts_area_info` (
- id UInt32 ,
- createDate Date ,
- userId UInt32 ,
- url String,
- income UInt8
- ) ENGINE=MergeTree()
- PARTITION BY toYYYYMM(createDate)
- ORDER BY (id,createDate,intHash32(userId))
- SAMPLE BY intHash32(userId)
- SETTINGS index_granularity = 8192
-
- #创建物化视图
- CREATE MATERIALIZED VIEW area_mv
- ENGINE SummingMergeTree
- PARTITION BY toYYYYMM(createDate)
- ORDER BY (id,createDate,intHash32(userId))
- AS
- select * from ts_area_info;

新生成的物化视图:
关键字段:
populate:建表同步数据
final:去最新的数据
- #使用物化视图同步聚合表
- 1、创建明细表
- drop table tb_order;
- create table tb_order(
- id UInt8 ,
- createDate Date ,
- money UInt64
- )
- ENGINE =MergeTree()
- order by id;
-
- 2、插入数据
- insert into tb_order values(1,toDate(now()),100),
- (2,toDate(now()),100),
- (3,toDate(now()),100),
- (1,toDate(now()),100),
- (2,toDate(now()),200),
- (3,toDate(now()),300);
-
- 3、创建物化视图同步数据
- CREATE MATERIALIZED VIEW order_mv
- ENGINE AggregatingMergeTree()
- PARTITION BY toYYYYMM(createDate)
- ORDER BY (id,createDate)
- POPULATE AS
- select id,createDate,sumState(money) as ms from tb_order
- GROUP BY id,createDate;
-
- 4、查询物化视图
- select id,createDate,sumMerge(ms) from order_mv GROUP BY id,createDate;
-
- 5、重新插入查看同步数据
- insert into tb_order values(1,toDate(now()),100),(2,toDate(now()),100);
-
- insert into tb_order values(1,toDate('2022-06-29'),100),(2,toDate('2022-06-29'),100);
-
- 6、查询订单表
- select * from tb_order;
注:
在建表时没有指定主键,会默认使用order by的字段作为主键