在没有物化视图功能之前,用户一般都是使用 Rollup 功能通过预聚合方式提升查询效率的。但是 Rollup 具有一定的局限性,他不能基于明细模型做预聚合。
物化视图则在覆盖了 Rollup 的功能的同时,还能支持更丰富的聚合函数。所以物化视图其实是 Rollup 的一个超集。
也就是说,之前 ALTER TABLE ADD ROLLUP 语法支持的功能现在均可以通过 CREATE MATERIALIZED VIEW 实现。
因为物化试图是需要占用机器资源的,所以不能每个select都建立一个物化视图,这里给出以下2个原则
如果物化视图只和某个特殊的查询很贴合,而其他查询均用不到这个物化视图。则会导致这张物化视图的性价比不高,既占用了集群的存储资源,还不能为更多的查询服务。
创建物化视图是一个异步的操作,也就是说用户成功提交创建任务后,Doris 会在后台对存量的数据进行计算,直到创建成功。
# 创建物化视图
CREATE MATERIALIZED VIEW 视图名称 AS selec .....
# 查看帮助
HELP CREATE MATERIALIZED VIEW
查看当前表的物化视图
desc tableName all;
CREATE TABLE sales_records(
id INT COMMENT "销售记录的id",
seller_id INT COMMENT "销售员的id",
store_id INT COMMENT "门店的id",
sale_date DATE COMMENT "销售日期",
sale_amt BIGINT COMMENT "金额"
)
DISTRIBUTED BY HASH(id) BUCKETS 10;
基于这个Base表的数据提交一个创建物化视图的任务
CREATE MATERIALIZED VIEW mv_1 AS
SELECT seller_id, sale_date, SUM( sale_amt )
FROM sales_records
GROUP BY seller_id, sale_date;
desc sales_records all;
这里通过举例的方式,来说明select 语句是怎么匹配物化视图的
基于这个Base表的数据再次提交两个创建物化视图的任务
CREATE MATERIALIZED VIEW mv_1 AS
SELECT seller_id, sale_date, SUM( sale_amt )
FROM sales_records
GROUP BY seller_id, sale_date;
1. 是一个提供 seller_id, sale_date和SUM(sale_amt)字段的mv_1表,mv_1表的数据是通过 销售员id和销售日期分组
2. 如果要查询 销售员id和销售日期 对应的销售金额,那么优先匹配mv_1表。
CREATE MATERIALIZED VIEW mv_2 AS SELECT store_id,sale_date,SUM(sale_amt)
FROM sales_records
GROUP BY store_id,sale_date;
1. 是一个提供 store_id, sale_date 和SUM(sale_amt)字段的mv_2表,mv_2表的数据是通过 门店id和销售日期分组
2. 如果要查询 门店id和销售日期 对应的销售金额,那么优先匹配mv_2表。
CREATE MATERIALIZED VIEW mv_3 AS
SELECT seller_id,SUM(sale_amt)
FROM sales_records
GROUP BY seller_id;
1. 是一个提供 seller_id和SUM(sale_amt)字段的mv_3表,mv_3表的数据是通过 销售员id分组
2. 如果要查询 销售员id 对应的销售金额,那么优先匹配mv_3表。
根据查询的条件,从 候选集 的所有物化视图中,找到最优的物化视图
SELECT seller_id, SUM(sale_amt)
FROM sales_records
WHERE sale_date='2021-02010'
GROUP BY seller_id
获取候选集,目前候选集中包括所有的物化视图以及Base表共4个。
第1层过滤,先判断查询Where中的谓词涉及到的数据是否能从物化视图中得到,也就是销售时间列是否在表中存在。由于mv_3物化视图中 根本不存在销售时间列。所以在这一层过滤中,mv_3就被淘汰了。
第2层过滤,查询的分组列是否为候选集的分组列的子集,也就是销售员id是否为表中分组列的子集。由于mv_2物化视图中的分组列并不涉及销售员id。所以在这一层过滤中,mv_2也被淘汰了。
第3层过滤,查询的聚合列是否为候选集中聚合列的子集,也就是候选集中 是否存在SUM(sale_amt),这里Base表和mv_1物化视图表均满足标准。
第4层过滤,看查询需要的列是否存在于候选集合的列中。也就是候选集中 是否存在seller_id,这里Base表和mv_1物化视图表均满足标准。
将查询改写为从mv_1中读取数据,过滤出日志为2月10日的mv_1中的数据然后返回即可。
SELECT seller_id, SUM(sale_amt)
FROM sales_records
WHERE sale_date='2021-02010'
GROUP BY seller_id
变为
SELECT seller_id, SUM(sale_amt)
FROM mv_1
WHERE sale_date='2021-02010'
GROUP BY seller_id
-- 检查物化视图是否构建完成
SHOW ALTER TABLE MATERIALIZED VIEW FROM test_db;
-- 删除物化视图
DROP MATERIALIZED VIEW mv_3 ON sales_records;
desc sales_records all;
删掉mv_3