一. 物化視圖概述
物化視圖是將預先計算(根據(jù)定義好的 SELECT 語句)好的數(shù)據(jù)集,存儲在 Doris 中的一個特殊的表孝扛。
物化視圖的出現(xiàn)主要是為了滿足用戶,既能對原始明細數(shù)據(jù)的任意維度分析拨脉,也能快速的對固定維度進行分析查詢辨赐。
適用場景:
- 分析需求覆蓋明細數(shù)據(jù)查詢以及固定維度查詢兩方面。
- 查詢僅涉及表中的很小一部分列或行诲祸。
- 查詢包含一些耗時處理操作浊吏,比如:時間很久的聚合操作等而昨。
- 查詢需要匹配不同前綴索引。
優(yōu)勢:
- 對于那些經(jīng)常重復的使用相同的子查詢結(jié)果的查詢性能大幅提升找田。
- Doris自動維護物化視圖的數(shù)據(jù)歌憨,無論是新的導入,還是刪除操作都能保證base 表和物化視圖表的數(shù)據(jù)一致性墩衙。無需任何額外的人工維護成本务嫡。
- 查詢時,會自動匹配到最優(yōu)物化視圖漆改,并直接從物化視圖中讀取數(shù)據(jù)心铃。
物化視圖 VS Rollup:
在沒有物化視圖功能之前,用戶一般都是使用 Rollup 功能通過預聚合方式提升查詢效率的挫剑。但是 Rollup 具有一定的局限性去扣,他不能基于明細模型做預聚合。
物化視圖則在覆蓋了 Rollup 的功能的同時樊破,還能支持更豐富的聚合函數(shù)愉棱。所以物化視圖其實是 Rollup 的一個超集。
也就是說哲戚,之前 ALTER TABLE ADD ROLLUP 語法支持的功能現(xiàn)在均可以通過 CREATE MATERIALIZED VIEW 實現(xiàn)奔滑。
局限性:
物化視圖的聚合函數(shù)的參數(shù)不支持表達式僅支持單列,比如: sum(a+b)不支持惫恼。
如果刪除語句的條件列档押,在物化視圖中不存在,則不能進行刪除操作祈纯。如果一定要刪除數(shù)據(jù),則需要先將物化視圖刪除叼耙,然后方可刪除數(shù)據(jù)腕窥。
單表上過多的物化視圖會影響導入的效率:導入數(shù)據(jù)時,物化視圖和 base 表數(shù)據(jù)是同步更新的筛婉,如果一張表的物化視圖表超過10張簇爆,則有可能導致導入速度很慢。這就像單次導入需要同時導入10張表數(shù)據(jù)是一樣的爽撒。
相同列入蛆,不同聚合函數(shù),不能同時出現(xiàn)在一張物化視圖中硕勿,比如:select sum(a), min(a) from table 不支持哨毁。
物化視圖針對 Unique Key數(shù)據(jù)模型,只能改變列順序源武,不能起到聚合的作用扼褪,所以在Unique Key模型上不能通過創(chuàng)建物化視圖的方式對數(shù)據(jù)進行粗粒度聚合操作
二. 使用物化視圖
Doris 系統(tǒng)提供了一整套對物化視圖的 DDL 語法想幻,包括創(chuàng)建,查看话浇,刪除脏毯。DDL 的語法和 PostgreSQL, Oracle都是一致的。
2.1 創(chuàng)建物化視圖
這里首先你要根據(jù)你的查詢語句的特點來決定創(chuàng)建一個什么樣的物化視圖幔崖。這里并不是說你的物化視圖定義和你的某個查詢語句一模一樣就最好食店。這里有兩個原則:
從查詢語句中抽象出,多個查詢共有的分組和聚合方式作為物化視圖的定義赏寇。
不需要給所有維度組合都創(chuàng)建物化視圖叛买。
首先第一個點,一個物化視圖如果抽象出來蹋订,并且多個查詢都可以匹配到這張物化視圖率挣。這種物化視圖效果最好。因為物化視圖的維護本身也需要消耗資源露戒。
如果物化視圖只和某個特殊的查詢很貼合椒功,而其他查詢均用不到這個物化視圖。則會導致這張物化視圖的性價比不高智什,既占用了集群的存儲資源动漾,還不能為更多的查詢服務。
所以用戶需要結(jié)合自己的查詢語句荠锭,以及數(shù)據(jù)維度信息去抽象出一些物化視圖的定義旱眯。
第二點就是,在實際的分析查詢中证九,并不會覆蓋到所有的維度分析删豺。所以給常用的維度組合創(chuàng)建物化視圖即可,從而到達一個空間和時間上的平衡愧怜。
創(chuàng)建物化視圖是一個異步的操作呀页,也就是說用戶成功提交創(chuàng)建任務后,Doris 會在后臺對存量的數(shù)據(jù)進行計算拥坛,直到創(chuàng)建成功蓬蝶。
具體的語法可以通過 Mysql 協(xié)議鏈接 Doris 并輸入下面命令查看:
HELP CREATE MATERIALIZED VIEW
2.2 支持聚合函數(shù)
目前物化視圖創(chuàng)建語句支持的聚合函數(shù)有:
- SUM, MIN, MAX (Version 0.12)
- COUNT, BITMAP_UNION, HLL_UNION (Version 0.13)
- BITMAP_UNION 的形式必須為:BITMAP_UNION(TO_BITMAP(COLUMN)) column 列的類型只能是整數(shù)(largeint也不支持), 或者 BITMAP_UNION(COLUMN) 且 base 表為 AGG 模型。
- HLL_UNION 的形式必須為:HLL_UNION(HLL_HASH(COLUMN)) column 列的類型不能是 DECIMAL , 或者 HLL_UNION(COLUMN) 且 base 表為 AGG 模型猜惋。
2.3 更新策略
為保證物化視圖表和 Base 表的數(shù)據(jù)一致性, Doris 會將導入丸氛,刪除等對 base 表的操作都同步到物化視圖表中。并且通過增量更新的方式來提升更新效率著摔。通過事務方式來保證原子性缓窜。
比如如果用戶通過 INSERT 命令插入數(shù)據(jù)到 base 表中,則這條數(shù)據(jù)會同步插入到物化視圖中。當 base 表和物化視圖表均寫入成功后雹洗,INSERT 命令才會成功返回香罐。
2.4 查詢自動匹配
物化視圖創(chuàng)建成功后,用戶的查詢不需要發(fā)生任何改變时肿,也就是還是查詢的 base 表庇茫。Doris 會根據(jù)當前查詢的語句去自動選擇一個最優(yōu)的物化視圖,從物化視圖中讀取數(shù)據(jù)并計算螃成。
用戶可以通過 EXPLAIN 命令來檢查當前查詢是否使用了物化視圖旦签。
物化視圖中的聚合和查詢中聚合的匹配關系:
其中 bitmap 和 hll 的聚合函數(shù)在查詢匹配到物化視圖后,查詢的聚合算子會根據(jù)物化視圖的表結(jié)構(gòu)進行一個改寫寸宏。
2.5 查詢物化視圖
查看當前表都有哪些物化視圖宁炫,以及他們的表結(jié)構(gòu)都是什么樣的。通過下面命令:
MySQL [test]> desc mv_test all;
+-----------+---------------+-----------------+----------+------+-------+---------+--------------+
| IndexName | IndexKeysType | Field | Type | Null | Key | Default | Extra |
+-----------+---------------+-----------------+----------+------+-------+---------+--------------+
| mv_test | DUP_KEYS | k1 | INT | Yes | true | NULL | |
| | | k2 | BIGINT | Yes | true | NULL | |
| | | k3 | LARGEINT | Yes | true | NULL | |
| | | k4 | SMALLINT | Yes | false | NULL | NONE |
| | | | | | | | |
| mv_2 | AGG_KEYS | k2 | BIGINT | Yes | true | NULL | |
| | | k4 | SMALLINT | Yes | false | NULL | MIN |
| | | k1 | INT | Yes | false | NULL | MAX |
| | | | | | | | |
| mv_3 | AGG_KEYS | k1 | INT | Yes | true | NULL | |
| | | to_bitmap(`k2`) | BITMAP | No | false | | BITMAP_UNION |
| | | | | | | | |
| mv_1 | AGG_KEYS | k4 | SMALLINT | Yes | true | NULL | |
| | | k1 | BIGINT | Yes | false | NULL | SUM |
| | | k3 | LARGEINT | Yes | false | NULL | SUM |
| | | k2 | BIGINT | Yes | false | NULL | MIN |
+-----------+---------------+-----------------+----------+------+-------+---------+--------------+
可以看到當前 mv_test 表一共有三張物化視圖:mv_1, mv_2 和 mv_3氮凝,以及他們的表結(jié)構(gòu)羔巢。
2.6 刪除物化視圖
如果用戶不再需要物化視圖,則可以通過命令刪除物化視圖罩阵。
具體的語法可以通過 Mysql 協(xié)議鏈接 Doris 輸入下面命令查看:
HELP DROP MATERIALIZED VIEW
三. 案例
測試數(shù)據(jù):
mysql> show create table ods_fact_sale\G
*************************** 1. row ***************************
Table: ods_fact_sale
Create Table: CREATE TABLE `ods_fact_sale` (
`id` bigint(20) NULL COMMENT "",
`sale_date` varchar(100) NULL COMMENT "",
`prod_name` varchar(32) NULL COMMENT "",
`sale_nums` bigint(20) SUM NULL DEFAULT "0" COMMENT "",
INDEX b_odsfactsale_prodname (`prod_name`) USING BITMAP COMMENT '產(chǎn)品名稱'
) ENGINE=OLAP
AGGREGATE KEY(`id`, `sale_date`, `prod_name`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`id`) BUCKETS 10
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory" = "false",
"storage_format" = "V2"
)
1 row in set (0.00 sec)
mysql> select count(*) from ods_fact_sale;
+-----------+
| count(*) |
+-----------+
| 767830000 |
+-----------+
1 row in set (16.94 sec)
此時開啟一個查詢:
select sale_date,sum(sale_nums) as all_nums
from ods_fact_sale
group by sale_date;
創(chuàng)建物化視圖:
CREATE MATERIALIZED VIEW mv_odsfactsale_1 as
select sale_date,sum(sale_nums) as all_nums
from ods_fact_sale
group by sale_date;
測試記錄:
mysql> CREATE MATERIALIZED VIEW mv_odsfactsale_1 as
-> select sale_date,sum(sale_nums) as all_nums
-> from ods_fact_sale
-> group by sale_date;
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql>
mysql>
mysql>
mysql> desc ods_fact_sale all;
+------------------+---------------+-----------+--------------+------+-------+---------+-------+---------+
| IndexName | IndexKeysType | Field | Type | Null | Key | Default | Extra | Visible |
+------------------+---------------+-----------+--------------+------+-------+---------+-------+---------+
| ods_fact_sale | AGG_KEYS | id | BIGINT | Yes | true | NULL | | true |
| | | sale_date | VARCHAR(100) | Yes | true | NULL | | true |
| | | prod_name | VARCHAR(32) | Yes | true | NULL | | true |
| | | sale_nums | BIGINT | Yes | false | 0 | SUM | true |
| | | | | | | | | |
| mv_odsfactsale_1 | AGG_KEYS | sale_date | VARCHAR(100) | Yes | true | NULL | | true |
| | | sale_nums | BIGINT | Yes | false | 0 | SUM | true |
+------------------+---------------+-----------+--------------+------+-------+---------+-------+---------+
7 rows in set (0.00 sec)