接上篇----------Doris 建表示例
Doris 支持兩層的數據劃分。第一層是 Partition,支持 Range 和 List 的劃分方式。第二層是 Bucket(Tablet),僅支持 Hash 的劃分方式。
也可以僅使用一層分區。使用一層分區時,只支持 Bucket 劃分。
Partition
-
Partition 列可以指定一列或多列。分區類必須為 KEY 列。
-
不論分區列是什么類型,在寫分區值時,都需要加雙引號。
-
分區數量理論上沒有上限。
-
當不使用 Partition 建表時,系統會自動生成一個和表名同名的,全值范圍的Partition。該 Partition 對用戶不可見,并且不可刪改。
Range 分區
分區列通常為時間列,以方便的管理新舊數據。不可添加范圍重疊的分區。 Partition 指定范圍的方式
VALUES LESS THAN (...) 僅指定上界,系統會將前一個分區的上界作為該分區的下界,生成一個左閉右開的區間。分區的刪除不會改變已存在分區的范圍。刪除分區可能出現空洞。
VALUES [...) 指定同時指定上下界,生成一個左閉右開的區間。
通過 VALUES [...) 同時指定上下界比較容易理解。這里舉例說明,當使用 VALUES LESS THAN (...) 語句進行分區的增刪操作時,分區范圍的變化情況:
(1)如上 expamle_range_tbl 示例,當建表完成后,會自動生成如下 3 個分區:
p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)
(2)增加一個分區 p201705 VALUES LESS THAN ("2017-06-01"),分區結果如下:
p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)
p201705: [2017-04-01, 2017-06-01)
(3)此時刪除分區 p201703,則分區結果如下:
p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)
注意到 p201702 和 p201705 的分區范圍并沒有發生變化,而這兩個分區之間,出現了一個空洞:[2017-03-01, 2017-04-01)。即如果導入的數據范圍在這個空洞范圍內,是無法導入的。
(4)繼續刪除分區 p201702,分區結果如下:
p201701: [MIN_VALUE, 2017-02-01)
p201705: [2017-04-01, 2017-06-01)
空洞范圍變為:[2017-02-01, 2017-04-01)
(5)現在增加一個分區 p201702new VALUES LESS THAN ("2017-03-01"),分區結果如下:
p201701: [MIN_VALUE, 2017-02-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)
可以看到空洞范圍縮小為:[2017-03-01, 2017-04-01)
(6)現在刪除分區 p201701,并添加分區 p201612 VALUES LESS THAN ("2017-01-01"),分區結果如下:
p201612: [MIN_VALUE, 2017-01-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)
即出現了一個新的空洞:[2017-01-01, 2017-02-01)
List 分區
分 區 列支 持 BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR, VARCHAR 數據類型,分區值為枚舉值。只有當數據為目標分區枚舉值
其中之一時,才可以命中分區。不可添加范圍重疊的分區。
Partition 支持通過 VALUES IN (...) 來指定每個分區包含的枚舉值。下面通過示例說明,進行分區的增刪操作時,分區的變化。
(1)如上 example_list_tbl 示例,當建表完成后,會自動生成如下 3 個分區:
p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_jp: ("Tokyo")
(2)增加一個分區 p_uk VALUES IN ("London"),分區結果如下:
p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_jp: ("Tokyo")
p_uk: ("London")
(3)刪除分區 p_jp,分區結果如下:
p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_uk: ("London")
Bucket
(1)如果使用了 Partition,則 DISTRIBUTED ... 語句描述的是數據在各個分區內的劃分規則。如果不使用 Partition,則描述的是對整個表的數據的劃分規則。
(2)分桶列可以是多列,但必須為 Key 列。分桶列可以和 Partition 列相同或不同。
(3)分桶列的選擇,是在 查詢吞吐 和 查詢并發 之間的一種權衡:
-
① 如果選擇多個分桶列,則數據分布更均勻。如果一個查詢條件不包含所有分桶列的等值條件,那么該查詢會觸發所有分桶同時掃描,這樣查詢的吞吐會增加,單個查詢的延遲隨之降低。這個方式適合大吞吐低并發的查詢場景。
-
② 如果僅選擇一個或少數分桶列,則對應的點查詢可以僅觸發一個分桶掃描。此時,當多個點查詢并發時,這些查詢有較大的概率分別觸發不同的分桶掃描,各個查詢之間的 IO 影響較小(尤其當不同桶分布在不同磁盤上時),所以這種方式適合高并發的點查詢場景。
(4)分桶的數量理論上沒有上限。
使用復合分區的場景
以下場景推薦使用復合分區
(1)有時間維度或類似帶有有序值的維度,可以以這類維度列作為分區列。分區粒度可以根據導入頻次、分區數據量等進行評估。
(2)歷史數據刪除需求:如有刪除歷史數據的需求(比如僅保留最近 N 天的數據)。使用復合分區,可以通過刪除歷史分區來達到目的。也可以通過在指定分區內發送 DELETE 語句進行數據刪除。
(3)解決數據傾斜問題:每個分區可以單獨指定分桶數量。如按天分區,當每天的數據量差異很大時,可以通過指定分區的分桶數,合理劃分不同分區的數據,分桶列建議選擇區分度大的列。
多列分區
Doris 支持指定多列作為分區列,示例如下:
1)Range 分區
PARTITION BY RANGE(`date`, `id`)
(PARTITION `p201701_1000` VALUES LESS THAN ("2017-02-01", "1000"),PARTITION `p201702_2000` VALUES LESS THAN ("2017-03-01", "2000"),PARTITION `p201703_all` VALUES LESS THAN ("2017-04-01")
)
指定?date
(DATE 類型) 和?id
(INT 類型) 作為分區列。以上示例最終得到的分區如下:
p201701_1000: [(MIN_VALUE, MIN_VALUE), ("2017-02-01", "1000") )
p201702_2000: [("2017-02-01", "1000"), ("2017-03-01", "2000") )
p201703_all: [("2017-03-01", "2000"), ("2017-04-01", MIN_VALUE))
注意,最后一個分區用戶缺省只指定了?date
?列的分區值,所以?id
?列的分區值會默認填充?MIN_VALUE
。當用戶插入數據時,分區列值會按照順序依次比較,最終得到對應的分區。舉例如下:
數據 --> 分區
2017-01-01, 200 --> p201701_1000
2017-01-01, 2000 --> p201701_1000
2017-02-01, 100 --> p201701_1000
2017-02-01, 2000 --> p201702_2000
2017-02-15, 5000 --> p201702_2000
2017-03-01, 2000 --> p201703_all
2017-03-10, 1 --> p201703_all
2017-04-01, 1000 --> 無法導入
2017-05-01, 1000 --> 無法導入
2)List 分區
PARTITION BY LIST(`id`, `city`)
(PARTITION `p1_city` VALUES IN (("1", "Beijing"), ("1", "Shanghai")),PARTITION `p2_city` VALUES IN (("2", "Beijing"), ("2", "Shanghai")),PARTITION `p3_city` VALUES IN (("3", "Beijing"), ("3", "Shanghai"))
)
指定?id
(INT 類型) 和?city
(VARCHAR 類型) 作為分區列。最終得到的分區如下:
p1_city: [("1", "Beijing"), ("1", "Shanghai")]
p2_city: [("2", "Beijing"), ("2", "Shanghai")]
p3_city: [("3", "Beijing"), ("3", "Shanghai")]
當用戶插入數據時,分區列值會按照順序依次比較,最終得到對應的分區。舉例如下:
數據 ---> 分區
1, Beijing ---> p1_city
1, Shanghai ---> p1_city
2, Shanghai ---> p2_city
3, Beijing ---> p3_city
1, Tianjin ---> 無法導入
4, Beijing ---> 無法導入
接下篇----------Doris的PROPERTIES與ENGINE