Apache Doris——物化視圖

八、物化視圖

物化視圖就是包含了查詢結(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塔猾,一起剝皮案震驚了整個濱河市篙骡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丈甸,老刑警劉巖糯俗,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異睦擂,居然都是意外死亡得湘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門顿仇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淘正,“玉大人,你說我怎么就攤上這事臼闻『柽海” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵述呐,是天一觀的道長惩淳。 經(jīng)常有香客問我,道長乓搬,這世上最難降的妖魔是什么思犁? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮进肯,結(jié)果婚禮上激蹲,老公的妹妹穿的比我還像新娘。我一直安慰自己江掩,他們只是感情好托呕,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著频敛,像睡著了一般项郊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斟赚,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天着降,我揣著相機與錄音,去河邊找鬼拗军。 笑死任洞,一個胖子當著我的面吹牛蓄喇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播交掏,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼妆偏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盅弛?” 一聲冷哼從身側(cè)響起钱骂,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挪鹏,沒想到半個月后见秽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡讨盒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年解取,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片返顺。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡禀苦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遂鹊,到底是詐尸還是另有隱情振乏,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布稿辙,位于F島的核電站,受9級特大地震影響气忠,放射性物質(zhì)發(fā)生泄漏邻储。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一旧噪、第九天 我趴在偏房一處隱蔽的房頂上張望吨娜。 院中可真熱鬧,春花似錦淘钟、人聲如沸宦赠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勾扭。三九已至,卻和暖如春铁瞒,著一層夾襖步出監(jiān)牢的瞬間妙色,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工慧耍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留身辨,地道東北人丐谋。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像煌珊,于是被迫代替她去往敵國和親号俐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容