八、物化視圖
物化視圖就是包含了查詢結(jié)果的數(shù)據(jù)庫對象蹂析,可能是對遠程數(shù)據(jù)的本地copy管削,也可能是一個表或多表join后結(jié)果的行或列的子集,也可能是聚合后的結(jié)果斩箫。說白了,就是預(yù)先存儲查詢結(jié)果的一種數(shù)據(jù)庫對象撵儿。
在Doris中的物化視圖乘客,就是查詢結(jié)果預(yù)先存儲起來的特殊的表。
物化視圖的出現(xiàn)主要是為了滿足用戶淀歇,既能對原始明細數(shù)據(jù)的任意維度分析易核,也能快速的對固定維度進行分析查詢。
適用場景
- 1浪默、分析需求覆蓋明細數(shù)據(jù)查詢以及固定維度查詢兩方面牡直;
- 2缀匕、查詢僅涉及表中的很小一部分列或行;
- 3井氢、查詢包含一些耗時處理操作弦追,比如:時間很久的聚合操作等;
- 4花竞、查詢需要匹配不同前綴索引劲件。
優(yōu)勢
- 1、對于那些經(jīng)常重復(fù)的使用相同的子查詢結(jié)果的查詢性能大幅提升约急;
- 2零远、Doris自動維護物化視圖的數(shù)據(jù),無論是新的導(dǎo)入厌蔽,還是刪除操作都能保證base表和物化視圖表的數(shù)據(jù)一致性牵辣。無需任何額外的人工維護成本;
- 3奴饮、查詢時纬向,會自動匹配到最優(yōu)物化視圖,并直接從物化視圖中讀取數(shù)據(jù)戴卜。
自動維護物化視圖的數(shù)據(jù)會造成一些維護開銷逾条,會在后面的物化視圖的局限性中展開說明。
物化視圖和Rollup
在沒有物化視圖功能之前投剥,用戶一般都是使用Rollup功能通過預(yù)聚合方式提升查詢效率的师脂。但是 Rollup具有一定的局限性,他不能基于明細模型做預(yù)聚合江锨。
物化視圖則在覆蓋了Rollup的功能的同時吃警,還能支持更豐富的聚合函數(shù)。所以物化視圖其實是Rollup的一個超集啄育。也就是說酌心,之前ALTER TABLE ADD ROLLUP語法支持的功能現(xiàn)在均可以通CREATE MATERIALIZED VIEW實現(xiàn)。
原理
Doris系統(tǒng)提供了一整套對物化視圖的DDL語法挑豌,包括創(chuàng)建谒府,查看,刪除浮毯。DDL 的語法和PostgreSQL, Oracle都是一致的。但是Doris目前創(chuàng)建物化視圖只能在單表操作泰鸡,不支持join债蓝。
創(chuàng)建物化視圖
首先要根據(jù)查詢語句的特點來決定創(chuàng)建一個什么樣的物化視圖。并不是說物化視圖定義和某個查詢語句一模一樣就最好盛龄。這里有兩個原則:
- 從查詢語句中抽象出饰迹,多個查詢共有的分組和聚合方式作為物化視圖的定義芳誓;
- 不需要給所有維度組合都創(chuàng)建物化視圖。
第一點啊鸭,一個物化視圖如果抽象出來锹淌,并且多個查詢都可以匹配到這張物化視圖。這種物化視圖效果最好赠制,因為物化視圖的維護本身也需要消耗資源赂摆。如果物化視圖只和某個特殊的查詢很貼合,而其他查詢均用不到這個物化視圖钟些。則會導(dǎo)致這張物化視圖的性價比不高烟号,既占用了集群的存儲資源,還不能為更多的查詢服務(wù)政恍。所以用戶需要結(jié)合自己的查詢語句汪拥,以及數(shù)據(jù)維度信息去抽象出一些物化視圖的定義。
第二點篙耗,在實際的分析查詢中迫筑,并不會覆蓋到所有的維度分析。所以給常用的維度組合創(chuàng)建物化視圖即可宗弯,從而到達一個空間和時間上的平衡脯燃。
通過下面命令就可以創(chuàng)建物化視圖了。創(chuàng)建物化視圖是一個異步的操作罕伯,也就是說用戶成功提交創(chuàng)建任務(wù)后曲伊,Doris會在后臺對存量的數(shù)據(jù)進行計算,直到創(chuàng)建成功追他。
具體的語法可以通過下面命令查看:HELP CREATE MATERIALIZED VIEW坟募,這里以一個銷售記錄表為例:
比如我們有一張銷售記錄明細表,存儲了每個交易的時間邑狸,銷售員懈糯,銷售門店,和金額单雾。提交完創(chuàng)建物化視圖的任務(wù)后赚哗,Doris就會異步在后臺生成物化視圖的數(shù)據(jù),構(gòu)建物化視圖硅堆。在構(gòu)建期間屿储,用戶依然可以正常的查詢和導(dǎo)入新的數(shù)據(jù)。創(chuàng)建任務(wù)會自動處理當前的存量數(shù)據(jù)和所有新到達的增量數(shù)據(jù)渐逃,從而保持和base表的數(shù)據(jù)一致性够掠。用戶不需關(guān)心一致性問題。
查詢
物化視圖創(chuàng)建完成后茄菊,用戶的查詢會根據(jù)規(guī)則自動匹配到最優(yōu)的物化視圖疯潭。比如我們有一張銷售記錄明細表赊堪,并且在這個明細表上創(chuàng)建了三張物化視圖。一個存儲了不同時間不同銷售員的售賣量竖哩,一個存儲了不同時間不同門店的銷售量哭廉,以及每個銷售員的總銷售量。當查詢7月19日相叁,各個銷售員都買了多少錢時遵绰,就可以匹配mv_1物化視圖,直接對mv_1 的數(shù)據(jù)進行查詢钝荡。
查詢自動匹配
物化視圖的自動匹配分為下面兩個步驟:
- 1街立、根據(jù)查詢條件刪選出一個最優(yōu)的物化視圖:這一步的輸入是所有候選物化視圖表的元數(shù)據(jù),根據(jù)查詢的條件從候選集中輸出最優(yōu)的一個物化視圖埠通;
*2赎离、根據(jù)選出的物化視圖對查詢進行改寫:這一步是結(jié)合上一步選擇出的最優(yōu)物化視圖,進行查詢的改寫端辱,最終達到直接查詢物化視圖的目的梁剔。
其中bitmap和hll的聚合函數(shù)在查詢匹配到物化視圖后,查詢的聚合算子會根據(jù)物化視圖的表結(jié)構(gòu)進行改寫舞蔽,如物化視圖的查詢所示荣病。
最優(yōu)路徑選擇
這里分為兩個步驟:
- 1、對候選集合進行一個過濾渗柿。只要是查詢的結(jié)果能從物化視圖數(shù)據(jù)計算(取部分行个盆,部分列,或部分行列的聚合)出都可以留在候選集中朵栖,過濾完成后候選集合大小>=1颊亮。
- 2、從候選集合中根據(jù)聚合程度陨溅,索引等條件選出一個最優(yōu)的也就是查詢花費最少物化視圖终惑。
這里再舉一個相對復(fù)雜的例子,來體現(xiàn)這個過程:
候選集過濾目前分為4層门扇,每一層過濾后去除不滿足條件的物化視圖雹有。比如查詢7月19日,各個銷售員都賣了多少錢臼寄,候選集中包括所有的物化視圖以及base表共4個:
第一層過濾先判斷查詢where中的謂詞涉及到的數(shù)據(jù)是否能從物化視圖中得到霸奕。也就是銷售時間列是否在表中存在。由于第三個物化視圖中根本不存在銷售時間列吉拳。所以在這一層過濾中质帅,mv_3就被淘汰了;
第二層是過濾查詢的分組列是否為候選集的分組列的子集。也就是銷售員id是否為表中分組列的子集临梗。由于第二個物化視圖中的分組列并不涉及銷售員id。所以在這一層過濾中稼跳,mv_2也被淘汰了盟庞;
第三層過濾是看查詢的聚合列是否為候選集中聚合列的子集。也就是對銷售額求和是否能從候選集的表中聚合得出汤善。這里base表和物化視圖表均滿足標準什猖;
最后一層是過濾看查詢需要的列是否存在于候選集合的列中。由于候選集合中的表均滿足標準红淡,所以最終候選集合中的表為銷售明細表不狮,以及mv_1。
候選集過濾完后輸出一個集合在旱,這個集合中的所有表都能滿足查詢的需求摇零。但每張表的查詢效率都不同。這時候就需要再這個集合根據(jù)前綴索引是否能匹配到桶蝎,以及聚合程度的高低來選出一個最優(yōu)的物化視圖驻仅。
從表結(jié)構(gòu)中可以看出,base表的銷售日期列是一個非排序列登渣,而物化視圖表的日期是一個排序列噪服,同時聚合程度上mv_1表明顯比base表高。所以最后選擇出mv_1作為該查詢的最優(yōu)匹配胜茧。
最后再根據(jù)選擇出的最優(yōu)解粘优,改寫查詢。剛才的查詢選中mv_1后呻顽,將查詢改寫為從mv_1中讀取數(shù)據(jù)雹顺,過濾出日志為7月19日的mv_1中的數(shù)據(jù)然后返回即可。
查詢改寫
有些情況下的查詢改寫還會涉及到查詢中的聚合函數(shù)的改寫芬位,比如業(yè)務(wù)方經(jīng)常會用到count distinct對PV无拗、UV進行計算。
例如:廣告點擊明細記錄表中存放哪個用戶點擊了什么廣告昧碉,從什么渠道點擊的英染,以及點擊的時間。并且在這個base表基礎(chǔ)上構(gòu)建了一個物化視圖表被饿,存儲了不同廣告不同渠道的用戶bitmap 值四康。由于bitmap union這種聚合方式本身會對相同的用戶user id進行一個去重聚合。當用戶查詢廣告在web端的uv的時候狭握,就可以匹配到這個物化視圖闪金。匹配到這個物化視圖表后就需要對查詢進行改寫,將之前的對用戶id求count(distinct)改為對物化視圖中bitmap union列求count。所以最后查詢?nèi)∥锘晥D的第一和第三行求bitmap聚合中有幾個值哎垦。
使用及限制
- 1囱嫩、目前支持的聚合函數(shù)包括,常用的sum漏设,min墨闲,max count,以及計算pv 郑口,uv鸳碧,留存率,等常用的去重算法hll_union犬性,和用于精確去重計算count(distinct)的算法bitmap_union瞻离;
- 2、物化視圖的聚合函數(shù)的參數(shù)不支持表達式僅支持單列乒裆,比如: sum(a+b)不支持套利;
- 3、使用物化視圖功能后缸兔,由于物化視圖實際上是損失了部分維度數(shù)據(jù)的日裙。所以對表的DML類型操作會有一些限制:如果表的物化視圖key中不包含刪除語句中的條件列,則刪除語句不能執(zhí)行惰蜜。比如想要刪除渠道為app端的數(shù)據(jù)昂拂,由于存在一個物化視圖并不包含渠道這個字段,則這個刪除不能執(zhí)行抛猖,因為刪除在物化視圖中無法被執(zhí)行格侯。這時候你只能把物化視圖先刪除,然后刪除完數(shù)據(jù)后财著,重新構(gòu)建一個新的物化視圖联四;
- 4、單表上過多的物化視圖會影響導(dǎo)入的效率:導(dǎo)入數(shù)據(jù)時撑教,物化視圖和base表數(shù)據(jù)是同步更新的朝墩,如果一張表的物化視圖表超過10張,則有可能導(dǎo)致導(dǎo)入速度很慢伟姐。這就像單次導(dǎo)入需要同時導(dǎo)入10張表數(shù)據(jù)是一樣的收苏;
- 5、相同列愤兵,不同聚合函數(shù)鹿霸,不能同時出現(xiàn)在一張物化視圖中,比如:select sum(a),min(a) from table不支持秆乳;
- 6懦鼠、物化視圖針對Unique Key數(shù)據(jù)模型钻哩,只能改變列順序,不能起到聚合的作用肛冶,所以在Unique Key模型上不能通過創(chuàng)建物化視圖的方式對數(shù)據(jù)進行粗粒度聚合操作街氢。
示例
示例1
創(chuàng)建表:
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");
插入數(shù)據(jù):
insert into sales_records values(1,2,3,'2020-02-02',10);
創(chuàng)建物化視圖:
create materialized view store_amt as select store_id, sum(sale_amt) from sales_records group by store_id;
由于創(chuàng)建物化視圖是一個異步的操作,用戶在提交完創(chuàng)建物化視圖任務(wù)后睦袖,需要異步地通過命令檢查物化視圖是否構(gòu)建完成:
mysql> SHOW ALTER TABLE MATERIALIZED VIEW FROM test;
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
| JobId | TableName | CreateTime | FinishTime | BaseIndexName | RollupIndexName | RollupId | TransactionId | State | Msg | Progress | Timeout |
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
| 10599 | example_site_visit2 | 2022-05-14 16:25:23 | 2022-05-14 16:25:44 | example_site_visit2 | rollup_cost_userid | 10600 | 12 | FINISHED | | NULL | 86400 |
| 10621 | example_site_visit2 | 2022-05-14 16:27:54 | 2022-05-14 16:28:24 | example_site_visit2 | rollup_city_age_cost_maxd_mind | 10622 | 13 | FINISHED | | NULL | 86400 |
| 10667 | sales_records | 2022-05-14 17:56:50 | 2022-05-14 17:57:14 | sales_records | store_amt | 10668 | 15 | FINISHED | | NULL | 86400 |
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
3 rows in set (0.00 sec)
檢驗當前查詢是否匹配到了合適的物化視圖:
mysql> EXPLAIN SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY store_id;
+-----------------------------------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:<slot 2> `store_id` | <slot 3> sum(`sale_amt`) |
| PARTITION: UNPARTITIONED |
| |
| RESULT SINK |
| |
| 4:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: <slot 2> `store_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 04 |
| UNPARTITIONED |
| |
| 3:AGGREGATE (merge finalize) |
| | output: sum(<slot 3> sum(`sale_amt`)) |
| | group by: <slot 2> `store_id` |
| | cardinality=-1 |
| | |
| 2:EXCHANGE |
| |
| PLAN FRAGMENT 2 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 02 |
| HASH_PARTITIONED: <slot 2> `store_id` |
| |
| 1:AGGREGATE (update serialize) |
| | STREAMING |
| | output: sum(`sale_amt`) |
| | group by: `store_id` |
| | cardinality=-1 |
| | |
| 0:OlapScanNode |
| TABLE: sales_records |
| PREAGGREGATION: ON |
| partitions=1/1 |
| rollup: store_amt |
| tabletRatio=10/10 |
| tabletList=10669,10671,10673,10675,10677,10679,10681,10683,10685,10687 |
| cardinality=0 |
| avgRowSize=12.0 |
| numNodes=1 |
+-----------------------------------------------------------------------------------+
47 rows in set (0.01 sec)
刪除物化視圖:
DROP MATERIALIZED VIEW 物化視圖名 on Base表名;
案例2:計算pv和uv
假設(shè)用戶的原始廣告點擊數(shù)據(jù)存儲在Doris阳仔,那么針對廣告PV, UV查詢就可以通過創(chuàng)建bitmap_union的物化視圖來提升查詢速度。
創(chuàng)建表:
create table advertiser_view_record(
time date,
advertiser varchar(10),
channel varchar(10),
user_id int
)
distributed by hash(time)
properties("replication_num" = "1");
插入數(shù)據(jù):
insert into advertiser_view_record values('2020-02-02','a','app',123);
創(chuàng)建物化視圖:
create materialized view advertiser_uv as
select advertiser, channel, bitmap_union(to_bitmap(user_id))
from advertiser_view_record
group by advertiser, channel;
在Doris中扣泊,count(distinct)聚合的結(jié)果和bitmap_union_count聚合的結(jié)果是完全一致的。而bitmap_union_count等于bitmap_union的結(jié)果求count嘶摊,所以如果查詢中涉及到count(distinct)則通過創(chuàng)建帶bitmap_union聚合的物化視圖方可加快查詢延蟹。
因為本身user_id是INT類型,所以在Doris中需要先將字段通過函數(shù)to_bitmap轉(zhuǎn)換為bitmap類型然后才可以進行bitmap_union聚合叶堆。
檢驗是否匹配到物化視圖:
mysql> explain SELECT advertiser, channel, count(distinct user_id) FROM advertiser_view_record GROUP BY advertiser, channel;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Explain String |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:<slot 7> `advertiser` | <slot 8> `channel` | <slot 9> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`) |
| PARTITION: UNPARTITIONED |
| |
| RESULT SINK |
| |
| 4:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: <slot 4> `advertiser`, <slot 5> `channel` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 04 |
| UNPARTITIONED |
| |
| 3:AGGREGATE (merge finalize) |
| | output: bitmap_union_count(<slot 6> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`)) |
| | group by: <slot 4> `advertiser`, <slot 5> `channel` |
| | cardinality=-1 |
| | |
| 2:EXCHANGE |
| |
| PLAN FRAGMENT 2 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: `default_cluster:test`.`advertiser_view_record`.`time` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 02 |
| HASH_PARTITIONED: <slot 4> `advertiser`, <slot 5> `channel` |
| |
| 1:AGGREGATE (update serialize) |
| | STREAMING |
| | output: bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`) |
| | group by: `advertiser`, `channel` |
| | cardinality=-1 |
| | |
| 0:OlapScanNode |
| TABLE: advertiser_view_record |
| PREAGGREGATION: ON |
| partitions=1/1 |
| rollup: advertiser_uv |
| tabletRatio=10/10 |
| tabletList=10715,10717,10719,10721,10723,10725,10727,10729,10731,10733 |
| cardinality=0 |
| avgRowSize=48.0 |
| numNodes=1 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
47 rows in set (0.01 sec)
在 EXPLAIN 的結(jié)果中阱飘,首先可以看到OlapScanNode的rollup屬性值為advertiser_uv。也就是說虱颗,查詢會直接掃描物化視圖的數(shù)據(jù)沥匈,說明匹配成功。其次對于user_id字段求count(distinct)被改寫為求bitmap_union_count(to_bitmap)忘渔,也就是通過bitmap的方式來達到精確去重的效果高帖。
案例3
用戶的原始表有(k1, k2, k3)三列。其中k1, k2為前綴索引列畦粮。這時候如果用戶查詢條件中包含 where k1=1 and k2=2就能通過索引加速查詢散址。但是有些情況下,用戶的過濾條件無法匹配到前綴索引宣赔,比如where k3=3预麸,則無法通過索引提升查詢速度,而創(chuàng)建以k3作為第一列的物化視圖就可以解決這個問題儒将。
查詢:
mysql> explain select record_id,seller_id,store_id from sales_records where store_id=3;
+-----------------------------------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:`record_id` | `seller_id` | `store_id` |
| PARTITION: UNPARTITIONED |
| |
| RESULT SINK |
| |
| 1:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 01 |
| UNPARTITIONED |
| |
| 0:OlapScanNode |
| TABLE: sales_records |
| PREAGGREGATION: ON |
| PREDICATES: `store_id` = 3 |
| partitions=1/1 |
| rollup: sales_records |
| tabletRatio=10/10 |
| tabletList=10646,10648,10650,10652,10654,10656,10658,10660,10662,10664 |
| cardinality=1 |
| avgRowSize=923.0 |
| numNodes=1 |
+-----------------------------------------------------------------------------------+
27 rows in set (0.01 sec)
創(chuàng)建物化視圖:
create materialized view mv_1 as
select
store_id,
record_id,
seller_id,
sale_date,
sale_amt
from sales_records;
通過上面語法創(chuàng)建完成后吏祸,物化視圖中既保留了完整的明細數(shù)據(jù),且物化視圖的前綴索引為 store_id列钩蚊。
查看表結(jié)構(gòu):
mysql> desc sales_records all;
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
| IndexName | IndexKeysType | Field | Type | Null | Key | Default | Extra | Visible |
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
| sales_records | DUP_KEYS | record_id | INT | Yes | true | NULL | | true |
| | | seller_id | INT | Yes | true | NULL | | true |
| | | store_id | INT | Yes | true | NULL | | true |
| | | sale_date | DATE | Yes | false | NULL | NONE | true |
| | | sale_amt | BIGINT | Yes | false | NULL | NONE | true |
| | | | | | | | | |
| mv_1 | DUP_KEYS | store_id | INT | Yes | true | NULL | | true |
| | | record_id | INT | Yes | true | NULL | | true |
| | | seller_id | INT | Yes | true | NULL | | true |
| | | sale_date | DATE | Yes | false | NULL | NONE | true |
| | | sale_amt | BIGINT | Yes | false | NULL | NONE | true |
| | | | | | | | | |
| store_amt | AGG_KEYS | store_id | INT | Yes | true | NULL | | true |
| | | sale_amt | BIGINT | Yes | false | NULL | SUM | true |
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
14 rows in set (0.00 sec)
查詢匹配:
mysql> explain select record_id,seller_id,store_id from sales_records where store_id=3;
+-----------------------------------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:`record_id` | `seller_id` | `store_id` |
| PARTITION: UNPARTITIONED |
| |
| RESULT SINK |
| |
| 1:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| OUTPUT EXPRS: |
| PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 01 |
| UNPARTITIONED |
| |
| 0:OlapScanNode |
| TABLE: sales_records |
| PREAGGREGATION: ON |
| PREDICATES: `store_id` = 3 |
| partitions=1/1 |
| rollup: mv_1 |
| tabletRatio=10/10 |
| tabletList=10737,10739,10741,10743,10745,10747,10749,10751,10753,10755 |
| cardinality=0 |
| avgRowSize=12.0 |
| numNodes=1 |
+-----------------------------------------------------------------------------------+
27 rows in set (0.00 sec)
這時候查詢就會直接從剛才創(chuàng)建的mv_1物化視圖中讀取數(shù)據(jù)贡翘。由于物化視圖對store_id是存在前綴索引的,查詢效率也會提升两疚。
修改表
使用ALTER TABLE命令可以對表進行修改床估,包括partition 、rollup诱渤、schema change丐巫、rename和index五種。語法:
ALTER TABLE [database.]table
alter_clause1[, alter_clause2, ...];
alter_clause 分為 partition 、rollup递胧、schema change碑韵、rename 和 index 五種。
rename
將名為 table1的表修改為table2:
ALTER TABLE table1 RENAME table2;
將表example_table中名為rollup1的rollup index修改為rollup2:
ALTER TABLE example_table RENAME ROLLUP rollup1 rollup2;
將表example_table中名為p1的partition修改為p2:
ALTER TABLE example_table RENAME PARTITION p1 p2;
partition
增加分區(qū), 使用默認分桶方式缎脾,如現(xiàn)有分區(qū)[MIN, 2013-01-01)祝闻,增加分區(qū)[2013-01-01, 2014-01-01):
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2014-01-01");
增加分區(qū),使用新的分桶數(shù):
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01") DISTRIBUTED BY HASH(k1) BUCKETS 20;
增加分區(qū)遗菠,使用新的副本數(shù):
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01") ("replication_num"="1");
修改分區(qū)副本數(shù):
ALTER TABLE example_db.my_table MODIFY PARTITION p1 SET("replication_num"="1");
批量修改指定分區(qū):
ALTER TABLE example_db.my_table MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");
批量修改所有分區(qū):
ALTER TABLE example_db.my_table MODIFY PARTITION (*) SET("storage_medium"="HDD");
刪除分區(qū):
ALTER TABLE example_db.my_table DROP PARTITION p1;
增加一個指定上下界的分區(qū):
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES [("2014-01-01"), ("2014-02-01"));
rollup
創(chuàng)建index: example_rollup_index联喘,基于base index(k1,k2,k3,v1,v2),列式存儲:
ALTER TABLE example_db.my_table
ADD ROLLUP example_rollup_index(k1, k3, v1, v2);
創(chuàng)建index: example_rollup_index2辙纬,基于example_rollup_index(k1,k3,v1,v2):
ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index2 (k1, v1) FROM example_rollup_index;
創(chuàng)建index: example_rollup_index3, 基于base index (k1,k2,k3,v1), 自定義rollup超時時間一小時:
ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index(k1, k3, v1) PROPERTIES("timeout" = "3600");
刪除index: example_rollup_index2:
ALTER TABLE example_db.my_table DROP ROLLUP example_rollup_index2;
表結(jié)構(gòu)變更
使用ALTER TABLE命令可以修改表的Schema豁遭,包括:增加列、刪除列贺拣、修改列類型蓖谢、改變列順序。以增加列為例:
我們新增一列uv譬涡,類型為BIGINT闪幽,聚合類型為SUM,默認值為0:
ALTER TABLE table1 ADD COLUMN uv BIGINT SUM DEFAULT '0' after pv;
提交成功后涡匀,可以通過以下命令查看作業(yè)進度:
SHOW ALTER TABLE COLUMN;
當作業(yè)狀態(tài)為FINISHED盯腌,則表示作業(yè)完成,新的Schema已生效陨瘩。
查看新的Schema:
DESC table1;
可以使用以下命令取消當前正在執(zhí)行的作業(yè):
CANCEL ALTER TABLE ROLLUP FROM table1;
更多可以參閱:HELP ALTER TABLE腊嗡。
刪除數(shù)據(jù)
Doris目前可以通過兩種方式刪除數(shù)據(jù):DELETE FROM語句和ALTER TABLE DROP PARTITION 語句。
條件刪除(drop from)
delete from語句類似標準delete語法拾酝,具體使用可以查看help delete;幫助燕少。
語法:
DELETE FROM table_name [PARTITION partition_name]
WHERE
column_name1 op { value | value_list } [ AND column_name2 op { value
| value_list } ...];
如:
delete from student_kafka where id=1;
注意事項:
- 1、該語句只能針對Partition級別進行刪除蒿囤。如果一個表有多個partition含有需要刪除的數(shù)據(jù)客们,則需要執(zhí)行多次針對不同Partition的delete 語句。而如果是沒有使用Partition的表材诽,partition的名稱即表名底挫;
- 2、where后面的條件謂詞只能針對Key列脸侥,并且謂詞之間建邓,只能通過AND連接。如果想實現(xiàn)OR的語義睁枕,需要執(zhí)行多條delete谎痢;
- 3、delete是一個同步命令曲稼,命令返回即表示執(zhí)行成功;
- 4契吉、從代碼實現(xiàn)角度,delete是一種特殊的導(dǎo)入操作诡渴。該命令所導(dǎo)入的內(nèi)容捐晶,也是一個新的數(shù)據(jù)版本,只是該版本中只包含命令中指定的刪除條件妄辩。在實際執(zhí)行查詢時惑灵,會根據(jù)這些條件進行查詢時過濾。所以眼耀,不建議大量頻繁使用delete命令泣棋,因為這可能導(dǎo)致查詢效率降低;
- 5畔塔、數(shù)據(jù)的真正刪除是在BE進行數(shù)據(jù)Compaction時進行的。所以執(zhí)行完delete命令后鸯屿,并不會立即釋放磁盤空間澈吨;
- 6、delete命令一個較強的限制條件是寄摆,在執(zhí)行該命令時谅辣,對應(yīng)的表,不能有正在進行的導(dǎo)入任務(wù)(包括PENDING婶恼、ETL桑阶、LOADING)。而如果有QUORUM_FINISHED狀態(tài)的導(dǎo)入任務(wù)勾邦,則可能可以執(zhí)行蚣录;
- 7、delete也有一個隱含的類似QUORUM_FINISHED的狀態(tài)眷篇。即如果 delete只在多數(shù)副本上完成了萎河,也會返回用戶成功。但是會在后臺生成一個異步的delete job(Async Delete Job)蕉饼,來繼續(xù)完成對剩余副本的刪除操作虐杯。如果此時通過show delete命令,可以看到這種任務(wù)在state一欄會顯示QUORUM_FINISHED昧港。
分區(qū)刪除(drop partition)
該命令可以直接刪除指定的分區(qū)擎椰。因為Partition是邏輯上最小的數(shù)據(jù)管理單元,所以使用DROP PARTITION命令可以很輕量地完成數(shù)據(jù)刪除工作创肥,并且不受load以及任何其他操作的限制达舒,同時不會影響查詢效率值朋,是比較推薦的一種數(shù)據(jù)刪除方式。該命令是同步命令休弃,執(zhí)行成功即生效吞歼。而后臺數(shù)據(jù)真正刪除的時間可能會延遲10分鐘左右。
參考:
https://blog.csdn.net/qq_37475168/article/details/125570856