物化視圖
物化視圖是將預(yù)先計算(根據(jù)定義好的 SELECT 語句)好的數(shù)據(jù)集,存儲在 Doris 中的一個特殊的表。
物化視圖的出現(xiàn)主要是為了滿足用戶,既能對原始明細(xì)數(shù)據(jù)的任意維度分析,也能快速的對固定維度進行分析查詢。
適用場景?
- 分析需求覆蓋明細(xì)數(shù)據(jù)查詢以及固定維度查詢兩方面。
- 查詢僅涉及表中的很小一部分列或行。
- 查詢包含一些耗時處理操作,比如:時間很久的聚合操作等。
- 查詢需要匹配不同前綴索引。
優(yōu)勢?
- 對于那些經(jīng)常重復(fù)的使用相同的子查詢結(jié)果的查詢性能大幅提升。
- Doris 自動維護物化視圖的數(shù)據(jù),無論是新的導(dǎo)入,還是刪除操作都能保證 Base 表和物化視圖表的數(shù)據(jù)一致性,無需任何額外的人工維護成本。
- 查詢時,會自動匹配到最優(yōu)物化視圖,并直接從物化視圖中讀取數(shù)據(jù)。
自動維護物化視圖的數(shù)據(jù)會造成一些維護開銷,會在后面的物化視圖的局限性中展開說明。
物化視圖 VS Rollup?
在沒有物化視圖功能之前,用戶一般都是使用 Rollup 功能通過預(yù)聚合方式提升查詢效率的。但是 Rollup 具有一定的局限性,他不能基于明細(xì)模型做預(yù)聚合。
物化視圖則在覆蓋了 Rollup 的功能的同時,還能支持更豐富的聚合函數(shù)。所以物化視圖其實是 Rollup 的一個超集。
也就是說,之前?ALTER TABLE ADD ROLLUP?語法支持的功能現(xiàn)在均可以通過?CREATE MATERIALIZED VIEW?實現(xiàn)。
使用物化視圖?
Doris 系統(tǒng)提供了一整套對物化視圖的 DDL 語法,包括創(chuàng)建,查看,刪除。DDL 的語法和 PostgreSQL, Oracle 都是一致的。
創(chuàng)建物化視圖?
這里首先你要根據(jù)你的查詢語句的特點來決定創(chuàng)建一個什么樣的物化視圖。這里并不是說你的物化視圖定義和你的某個查詢語句一模一樣就最好。這里有兩個原則:
- 從查詢語句中抽象出,多個查詢共有的分組和聚合方式作為物化視圖的定義。
- 不需要給所有維度組合都創(chuàng)建物化視圖。
首先第一個點,一個物化視圖如果抽象出來,并且多個查詢都可以匹配到這張物化視圖。這種物化視圖效果最好。因為物化視圖的維護本身也需要消耗資源。
如果物化視圖只和某個特殊的查詢很貼合,而其他查詢均用不到這個物化視圖。則會導(dǎo)致這張物化視圖的性價比不高,既占用了集群的存儲資源,還不能為更多的查詢服務(wù)。
所以用戶需要結(jié)合自己的查詢語句,以及數(shù)據(jù)維度信息去抽象出一些物化視圖的定義。
第二點就是,在實際的分析查詢中,并不會覆蓋到所有的維度分析。所以給常用的維度組合創(chuàng)建物化視圖即可,從而到達一個空間和時間上的平衡。
創(chuàng)建物化視圖是一個異步的操作,也就是說用戶成功提交創(chuàng)建任務(wù)后,Doris 會在后臺對存量的數(shù)據(jù)進行計算,直到創(chuàng)建成功。
具體的語法可查看CREATE MATERIALIZED VIEW?。
SinceVersion?2.0.0
在Doris 2.0
版本中我們對物化視圖的做了一些增強(在本文的最佳實踐4
中有具體描述)。我們建議用戶在正式的生產(chǎn)環(huán)境中使用物化視圖前,先在測試環(huán)境中確認(rèn)是預(yù)期中的查詢能否命中想要創(chuàng)建的物化視圖。
如果不清楚如何驗證一個查詢是否命中物化視圖,可以閱讀本文的最佳實踐1
。
與此同時,我們不建議用戶在同一張表上建多個形態(tài)類似的物化視圖,這可能會導(dǎo)致多個物化視圖之間的沖突使得查詢命中失敗(在新優(yōu)化器中這個問題會有所改善)。建議用戶先在測試環(huán)境中驗證物化視圖和查詢是否滿足需求并能正常使用。
支持聚合函數(shù)?
目前物化視圖創(chuàng)建語句支持的聚合函數(shù)有:
- SUM, MIN, MAX (Version 0.12)
- COUNT, BITMAP_UNION, HLL_UNION (Version 0.13)
更新策略?
為保證物化視圖表和 Base 表的數(shù)據(jù)一致性, Doris 會將導(dǎo)入,刪除等對 Base 表的操作都同步到物化視圖表中。并且通過增量更新的方式來提升更新效率。通過事務(wù)方式來保證原子性。
比如如果用戶通過 INSERT 命令插入數(shù)據(jù)到 Base 表中,則這條數(shù)據(jù)會同步插入到物化視圖中。當(dāng) Base 表和物化視圖表均寫入成功后,INSERT 命令才會成功返回。
查詢自動匹配?
物化視圖創(chuàng)建成功后,用戶的查詢不需要發(fā)生任何改變,也就是還是查詢的 Base 表。Doris 會根據(jù)當(dāng)前查詢的語句去自動選擇一個最優(yōu)的物化視圖,從物化視圖中讀取數(shù)據(jù)并計算。
用戶可以通過 EXPLAIN 命令來檢查當(dāng)前查詢是否使用了物化視圖。
物化視圖中的聚合和查詢中聚合的匹配關(guān)系:
物化視圖聚合 | 查詢中聚合 |
---|---|
sum | sum |
min | min |
max | max |
count | count |
bitmap_union | bitmap_union, bitmap_union_count, count(distinct) |
hll_union | hll_raw_agg, hll_union_agg, ndv, approx_count_distinct |
其中 bitmap 和 hll 的聚合函數(shù)在查詢匹配到物化視圖后,查詢的聚合算子會根據(jù)物化視圖的表結(jié)構(gòu)進行改寫。詳細(xì)見實例2。
查詢物化視圖?
查看當(dāng)前表都有哪些物化視圖,以及他們的表結(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 |
+-----------+---------------+-----------------+----------+------+-------+---------+--------------+
可以看到當(dāng)前?mv_test
?表一共有三張物化視圖:mv_1, mv_2 和 mv_3,以及他們的表結(jié)構(gòu)。
刪除物化視圖?
如果用戶不再需要物化視圖,則可以通過命令刪除物化視圖。
具體的語法可查看DROP MATERIALIZED VIEW
查看已創(chuàng)建的物化視圖?
用戶可以通過命令查看已創(chuàng)建的物化視圖的
具體的語法可查看SHOW CREATE MATERIALIZED VIEW
取消創(chuàng)建物化視圖?
CANCEL ALTER TABLE MATERIALIZED VIEW FROM db_name.table_name
最佳實踐1?
使用物化視圖一般分為以下幾個步驟:
- 創(chuàng)建物化視圖
- 異步檢查物化視圖是否構(gòu)建完成
- 查詢并自動匹配物化視圖
首先是第一步:創(chuàng)建物化視圖
假設(shè)用戶有一張銷售記錄明細(xì)表,存儲了每個交易的交易 id,銷售員,售賣門店,銷售時間,以及金額。建表語句和插入數(shù)據(jù)語句為:
create table sales_records(record_id int, seller_id int, store_id int, sale_date date, sale_amt bigint) distributed by hash(record_id) properties("replication_num" = "1");
insert into sales_records values(1,1,1,"2020-02-02",1);
這張?sales_records
?的表結(jié)構(gòu)如下:
MySQL [test]> desc sales_records;
+-----------+--------+------+-------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------+------+-------+---------+-------+
| record_id | INT | Yes | true | NULL | |
| seller_id | INT | Yes | true | NULL | |
| store_id | INT | Yes | true | NULL | |
| sale_date | DATE | Yes | false | NULL | NONE |
| sale_amt | BIGINT | Yes | false | NULL | NONE |
+-----------+--------+------+-------+---------+-------+
這時候如果用戶經(jīng)常對不同門店的銷售量進行一個分析查詢,則可以給這個?sales_records
?表創(chuàng)建一張以售賣門店分組,對相同售賣門店的銷售額求和的一個物化視圖。創(chuàng)建語句如下:
MySQL [test]> create materialized view store_amt as select store_id, sum(sale_amt) from sales_records group by store_id;
后端返回下圖,則說明創(chuàng)建物化視圖任務(wù)提交成功。
Query OK, 0 rows affected (0.012 sec)
第二步:檢查物化視圖是否構(gòu)建完成
由于創(chuàng)建物化視圖是一個異步的操作,用戶在提交完創(chuàng)建物化視圖任務(wù)后,需要異步的通過命令檢查物化視圖是否構(gòu)建完成。命令如下:
SHOW ALTER TABLE ROLLUP FROM db_name; (Version 0.12)
SHOW ALTER TABLE MATERIALIZED VIEW FROM db_name; (Version 0.13)
這個命令中?db_name
?是一個參數(shù), 你需要替換成自己真實的 db 名稱。命令的結(jié)果是顯示這個 db 的所有創(chuàng)建物化視圖的任務(wù)。結(jié)果如下:
+-------+---------------+---------------------+---------------------+---------------+-----------------+----------+---------------+-----------+-------------------------------------------------------------------------------------------------------------------------+----------+---------+
| JobId | TableName | CreateTime | FinishedTime | BaseIndexName | RollupIndexName | RollupId | TransactionId | State | Msg | Progress | Timeout |
+-------+---------------+---------------------+---------------------+---------------+-----------------+----------+---------------+-----------+-------------------------------------------------------------------------------------------------------------------------+----------+---------+
| 22036 | sales_records | 2020-07-30 20:04:28 | 2020-07-30 20:04:57 | sales_records | store_amt | 22037 | 5008 | FINISHED | | NULL | 86400 |
+-------+---------------+---------------------+---------------------+---------------+-----------------+----------+---------------+-----------+-------------------------------------------------------------------------------------------------------------------------+----------+---------+
其中 TableName 指的是物化視圖的數(shù)據(jù)來自于哪個表,RollupIndexName 指的是物化視圖的名稱叫什么。其中比較重要的指標(biāo)是 State。
當(dāng)創(chuàng)建物化視圖任務(wù)的 State 已經(jīng)變成 FINISHED 后,就說明這個物化視圖已經(jīng)創(chuàng)建成功了。這就意味著,查詢的時候有可能自動匹配到這張物化視圖了。
第三步:查詢
當(dāng)創(chuàng)建完成物化視圖后,用戶再查詢不同門店的銷售量時,就會直接從剛才創(chuàng)建的物化視圖?store_amt
?中讀取聚合好的數(shù)據(jù)。達到提升查詢效率的效果。
用戶的查詢依舊指定查詢?sales_records
?表,比如:
SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY store_id;
上面查詢就能自動匹配到?store_amt
。用戶可以通過下面命令,檢驗當(dāng)前查詢是否匹配到了合適的物化視圖。
EXPLAIN SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY store_id;
+----------------------------------------------------------------------------------------------+
| Explain String |
+----------------------------------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS: |
| <slot 4> `default_cluster:test`.`sales_records`.`mv_store_id` |
| <slot 5> sum(`default_cluster:test`.`sales_records`.`mva_SUM__`sale_amt``) |
| PARTITION: UNPARTITIONED |
| |
| VRESULT SINK |
| |
| 4:VEXCHANGE |
| offset: 0 |
| |
| PLAN FRAGMENT 1 |
| |
| PARTITION: HASH_PARTITIONED: <slot 4> `default_cluster:test`.`sales_records`.`mv_store_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 04 |
| UNPARTITIONED |
| |
| 3:VAGGREGATE (merge finalize) |
| | output: sum(<slot 5> sum(`default_cluster:test`.`sales_records`.`mva_SUM__`sale_amt``)) |
| | group by: <slot 4> `default_cluster:test`.`sales_records`.`mv_store_id` |
| | cardinality=-1 |
| | |
| 2:VEXCHANGE |
| offset: 0 |
| |
| PLAN FRAGMENT 2 |
| |
| PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 02 |
| HASH_PARTITIONED: <slot 4> `default_cluster:test`.`sales_records`.`mv_store_id` |
| |
| 1:VAGGREGATE (update serialize) |
| | STREAMING |
| | output: sum(`default_cluster:test`.`sales_records`.`mva_SUM__`sale_amt``) |
| | group by: `default_cluster:test`.`sales_records`.`mv_store_id` |
| | cardinality=-1 |
| | |
| 0:VOlapScanNode |
| TABLE: default_cluster:test.sales_records(store_amt), PREAGGREGATION: ON |
| partitions=1/1, tablets=10/10, tabletList=50028,50030,50032 ... |
| cardinality=1, avgRowSize=1520.0, numNodes=1 |
+----------------------------------------------------------------------------------------------+
從最底部的test.sales_records(store_amt)
可以表明這個查詢命中了store_amt
這個物化視圖。值得注意的是,如果表中沒有數(shù)據(jù),那么可能不會命中物化視圖。
最佳實踐2 PV,UV?
業(yè)務(wù)場景: 計算廣告的 UV,PV。
假設(shè)用戶的原始廣告點擊數(shù)據(jù)存儲在 Doris,那么針對廣告 PV, UV 查詢就可以通過創(chuàng)建?bitmap_union
?的物化視圖來提升查詢速度。
通過下面語句首先創(chuàng)建一個存儲廣告點擊數(shù)據(jù)明細(xì)的表,包含每條點擊的點擊時間,點擊的是什么廣告,通過什么渠道點擊,以及點擊的用戶是誰。
create table advertiser_view_record(time date, advertiser varchar(10), channel varchar(10), user_id int) distributed by hash(time) properties("replication_num" = "1");
insert into advertiser_view_record values("2020-02-02",'a','a',1);
原始的廣告點擊數(shù)據(jù)表結(jié)構(gòu)為:
MySQL [test]> desc advertiser_view_record;
+------------+-------------+------+-------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-------+---------+-------+
| time | DATE | Yes | true | NULL | |
| advertiser | VARCHAR(10) | Yes | true | NULL | |
| channel | VARCHAR(10) | Yes | false | NULL | NONE |
| user_id | INT | Yes | false | NULL | NONE |
+------------+-------------+------+-------+---------+-------+
4 rows in set (0.001 sec)
-
創(chuàng)建物化視圖
由于用戶想要查詢的是廣告的 UV 值,也就是需要對相同廣告的用戶進行一個精確去重,則查詢一般為:
SELECT advertiser, channel, count(distinct user_id) FROM advertiser_view_record GROUP BY advertiser, channel;
針對這種求 UV 的場景,我們就可以創(chuàng)建一個帶?
bitmap_union
?的物化視圖從而達到一個預(yù)先精確去重的效果。在 Doris 中,
count(distinct)
?聚合的結(jié)果和?bitmap_union_count
聚合的結(jié)果是完全一致的。而bitmap_union_count
?等于?bitmap_union
?的結(jié)果求 count, 所以如果查詢中涉及到?count(distinct)
?則通過創(chuàng)建帶?bitmap_union
?聚合的物化視圖方可加快查詢。針對這個 Case,則可以創(chuàng)建一個根據(jù)廣告和渠道分組,對?
user_id
?進行精確去重的物化視圖。MySQL [test]> create materialized view advertiser_uv as select advertiser, channel, bitmap_union(to_bitmap(user_id)) from advertiser_view_record group by advertiser, channel; Query OK, 0 rows affected (0.012 sec)
注意:因為本身 user_id 是一個 INT 類型,所以在 Doris 中需要先將字段通過函數(shù)?
to_bitmap
?轉(zhuǎn)換為 bitmap 類型然后才可以進行?bitmap_union
?聚合。創(chuàng)建完成后, 廣告點擊明細(xì)表和物化視圖表的表結(jié)構(gòu)如下:
MySQL [test]> desc advertiser_view_record all; +------------------------+---------------+----------------------+-------------+------+-------+---------+--------------+ | IndexName | IndexKeysType | Field | Type | Null | Key | Default | Extra | +------------------------+---------------+----------------------+-------------+------+-------+---------+--------------+ | advertiser_view_record | DUP_KEYS | time | DATE | Yes | true | NULL | | | | | advertiser | VARCHAR(10) | Yes | true | NULL | | | | | channel | VARCHAR(10) | Yes | false | NULL | NONE | | | | user_id | INT | Yes | false | NULL | NONE | | | | | | | | | | | advertiser_uv | AGG_KEYS | advertiser | VARCHAR(10) | Yes | true | NULL | | | | | channel | VARCHAR(10) | Yes | true | NULL | | | | | to_bitmap(`user_id`) | BITMAP | No | false | | BITMAP_UNION | +------------------------+---------------+----------------------+-------------+------+-------+---------+--------------+
-
查詢自動匹配
當(dāng)物化視圖表創(chuàng)建完成后,查詢廣告 UV 時,Doris 就會自動從剛才創(chuàng)建好的物化視圖?
advertiser_uv
?中查詢數(shù)據(jù)。比如原始的查詢語句如下:SELECT advertiser, channel, count(distinct user_id) FROM advertiser_view_record GROUP BY advertiser, channel;
在選中物化視圖后,實際的查詢會轉(zhuǎn)化為:
SELECT advertiser, channel, bitmap_union_count(to_bitmap(user_id)) FROM advertiser_uv GROUP BY advertiser, channel;
通過 EXPLAIN 命令可以檢驗到 Doris 是否匹配到了物化視圖:
mysql [test]>explain SELECT advertiser, channel, count(distinct user_id) FROM advertiser_view_record GROUP BY advertiser, channel; +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Explain String | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | PLAN FRAGMENT 0 | | OUTPUT EXPRS: | | <slot 9> `default_cluster:test`.`advertiser_view_record`.`mv_advertiser` | | <slot 10> `default_cluster:test`.`advertiser_view_record`.`mv_channel` | | <slot 11> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mva_BITMAP_UNION__to_bitmap_with_check(`user_id`)`) | | PARTITION: UNPARTITIONED | | | | VRESULT SINK | | | | 4:VEXCHANGE | | offset: 0 | | | | PLAN FRAGMENT 1 | | | | PARTITION: HASH_PARTITIONED: <slot 6> `default_cluster:test`.`advertiser_view_record`.`mv_advertiser`, <slot 7> `default_cluster:test`.`advertiser_view_record`.`mv_channel` | | | | STREAM DATA SINK | | EXCHANGE ID: 04 | | UNPARTITIONED | | | | 3:VAGGREGATE (merge finalize) | | | output: bitmap_union_count(<slot 8> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mva_BITMAP_UNION__to_bitmap_with_check(`user_id`)`)) | | | group by: <slot 6> `default_cluster:test`.`advertiser_view_record`.`mv_advertiser`, <slot 7> `default_cluster:test`.`advertiser_view_record`.`mv_channel` | | | cardinality=-1 | | | | | 2:VEXCHANGE | | offset: 0 | | | | PLAN FRAGMENT 2 | | | | PARTITION: HASH_PARTITIONED: `default_cluster:test`.`advertiser_view_record`.`time` | | | | STREAM DATA SINK | | EXCHANGE ID: 02 | | HASH_PARTITIONED: <slot 6> `default_cluster:test`.`advertiser_view_record`.`mv_advertiser`, <slot 7> `default_cluster:test`.`advertiser_view_record`.`mv_channel` | | | | 1:VAGGREGATE (update serialize) | | | STREAMING | | | output: bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mva_BITMAP_UNION__to_bitmap_with_check(`user_id`)`) | | | group by: `default_cluster:test`.`advertiser_view_record`.`mv_advertiser`, `default_cluster:test`.`advertiser_view_record`.`mv_channel` | | | cardinality=-1 | | | | | 0:VOlapScanNode | | TABLE: default_cluster:test.advertiser_view_record(advertiser_uv), PREAGGREGATION: ON | | partitions=1/1, tablets=10/10, tabletList=50075,50077,50079 ... | | cardinality=0, avgRowSize=48.0, numNodes=1 | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
在 EXPLAIN 的結(jié)果中,首先可以看到?
VOlapScanNode
?命中了?advertiser_uv
。也就是說,查詢會直接掃描物化視圖的數(shù)據(jù)。說明匹配成功。其次對于?
user_id
?字段求?count(distinct)
?被改寫為求?bitmap_union_count(to_bitmap)
。也就是通過 Bitmap 的方式來達到精確去重的效果。
最佳實踐3?
業(yè)務(wù)場景:匹配更豐富的前綴索引
用戶的原始表有 (k1, k2, k3) 三列。其中 k1, k2 為前綴索引列。這時候如果用戶查詢條件中包含?where k1=1 and k2=2
?就能通過索引加速查詢。
但是有些情況下,用戶的過濾條件無法匹配到前綴索引,比如?where k3=3
。則無法通過索引提升查詢速度。
創(chuàng)建以 k3 作為第一列的物化視圖就可以解決這個問題。
-
創(chuàng)建物化視圖
CREATE MATERIALIZED VIEW mv_1 as SELECT k3, k2, k1 FROM tableA ORDER BY k3;
通過上面語法創(chuàng)建完成后,物化視圖中既保留了完整的明細(xì)數(shù)據(jù),且物化視圖的前綴索引為 k3 列。表結(jié)構(gòu)如下:
MySQL [test]> desc tableA all; +-----------+---------------+-------+------+------+-------+---------+-------+ | IndexName | IndexKeysType | Field | Type | Null | Key | Default | Extra | +-----------+---------------+-------+------+------+-------+---------+-------+ | tableA | DUP_KEYS | k1 | INT | Yes | true | NULL | | | | | k2 | INT | Yes | true | NULL | | | | | k3 | INT | Yes | true | NULL | | | | | | | | | | | | mv_1 | DUP_KEYS | k3 | INT | Yes | true | NULL | | | | | k2 | INT | Yes | false | NULL | NONE | | | | k1 | INT | Yes | false | NULL | NONE | +-----------+---------------+-------+------+------+-------+---------+-------+
-
查詢匹配
這時候如果用戶的查詢存在 k3 列的過濾條件是,比如:
select k1, k2, k3 from table A where k3=3;
這時候查詢就會直接從剛才創(chuàng)建的 mv_1 物化視圖中讀取數(shù)據(jù)。物化視圖對 k3 是存在前綴索引的,查詢效率也會提升。
最佳實踐4?
SinceVersion?2.0.0
在Doris 2.0
中,我們對物化視圖所支持的表達式做了一些增強,本示例將主要體現(xiàn)新版本物化視圖對各種表達式的支持和提前過濾。文章來源:http://www.zghlxwxcb.cn/news/detail-660815.html
- 創(chuàng)建一個 Base 表并插入一些數(shù)據(jù)。
create table d_table (
k1 int null,
k2 int not null,
k3 bigint null,
k4 date null
)
duplicate key (k1,k2,k3)
distributed BY hash(k1) buckets 3
properties("replication_num" = "1");
insert into d_table select 1,1,1,'2020-02-20';
insert into d_table select 2,2,2,'2021-02-20';
insert into d_table select 3,-3,null,'2022-02-20';
- 創(chuàng)建一些物化視圖。
create materialized view k1a2p2ap3ps as select abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group by abs(k1)+k2+1;
create materialized view kymd as select year(k4),month(k4) from d_table where year(k4) = 2020; // 提前用where表達式過濾以減少物化視圖中的數(shù)據(jù)量。
- 用一些查詢測試是否成功命中物化視圖。
select abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group by abs(k1)+k2+1; // 命中k1a2p2ap3ps
select bin(abs(k1)+k2+1),sum(abs(k2+2)+k3+3) from d_table group by bin(abs(k1)+k2+1); // 命中k1a2p2ap3ps
select year(k4),month(k4) from d_table; // 無法命中物化視圖,因為where條件不匹配
select year(k4)+month(k4) from d_table where year(k4) = 2020; // 命中kymd
局限性?
- 如果刪除語句的條件列,在物化視圖中不存在,則不能進行刪除操作。如果一定要刪除數(shù)據(jù),則需要先將物化視圖刪除,然后方可刪除數(shù)據(jù)。
- 單表上過多的物化視圖會影響導(dǎo)入的效率:導(dǎo)入數(shù)據(jù)時,物化視圖和 Base 表數(shù)據(jù)是同步更新的,如果一張表的物化視圖表超過 10 張,則有可能導(dǎo)致導(dǎo)入速度很慢。這就像單次導(dǎo)入需要同時導(dǎo)入 10 張表數(shù)據(jù)是一樣的。
- 物化視圖針對 Unique Key數(shù)據(jù)模型,只能改變列順序,不能起到聚合的作用,所以在Unique Key模型上不能通過創(chuàng)建物化視圖的方式對數(shù)據(jù)進行粗粒度聚合操作
- 目前一些優(yōu)化器對sql的改寫行為可能會導(dǎo)致物化視圖無法被命中,例如k1+1-1被改寫成k1,between被改寫成<=和>=,day被改寫成dayofmonth,遇到這種情況需要手動調(diào)整下查詢和物化視圖的語句。
異常錯誤?
- DATA_QUALITY_ERROR: "The data quality does not satisfy, please check your data" 由于數(shù)據(jù)質(zhì)量問題或者 Schema Change 內(nèi)存使用超出限制導(dǎo)致物化視圖創(chuàng)建失敗。如果是內(nèi)存問題,調(diào)大
memory_limitation_per_thread_for_schema_change_bytes
參數(shù)即可。 注意:to_bitmap 的參數(shù)僅支持正整型, 如果原始數(shù)據(jù)中存在負(fù)數(shù),會導(dǎo)致物化視圖創(chuàng)建失敗。String 類型的字段可使用 bitmap_hash 或 bitmap_hash64 計算 Hash 值,并返回 Hash 值的 bitmap。
更多幫助?
關(guān)于物化視圖使用的更多詳細(xì)語法及最佳實踐,請參閱?CREATE MATERIALIZED VIEW?和?DROP MATERIALIZED VIEW?命令手冊,你也可以在 MySQL 客戶端命令行下輸入?HELP CREATE MATERIALIZED VIEW
?和HELP DROP MATERIALIZED VIEW
?獲取更多幫助信息。文章來源地址http://www.zghlxwxcb.cn/news/detail-660815.html
到了這里,關(guān)于Apache Doris 入門教程32:物化視圖的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!