Doris數據劃分

基礎概念

Tablet 和 Partition

在Doris的存儲引擎中,用戶數據被水平劃分爲若干個數據分片(Tablet,也叫數據分桶)。每個Tablet包含若干數據行。各個Tablet之間的數據沒有交集,並且在物理上是獨立存儲的。

多個Tablet在邏輯上歸屬於不同的分區(Partition)。一個Tablet只屬於一個Partition。而一個Partition包含若干個Tablet。Tablet是數據移動、複製等操作的最小物理存儲單元。

若干個Partition組成一個表。Partition可以視爲是邏輯上最小的管理單元。數據的導入與刪除,都可以或僅能針對一個Partition進行。

下面用一個建表操作說明數據劃分:

CREATE TABLE IF NOT EXISTS example_db.example_range_tbl
(
    `user_id` LARGEINT NOT NULL COMMENT "用戶id",
    `date` DATE NOT NULL COMMENT "數據灌入日期時間",
    `timestamp` DATETIME NOT NULL COMMENT "數據灌入的時間戳",
    `city` VARCHAR(20) COMMENT "用戶所在城市",
    `age` SMALLINT COMMENT "用戶年齡",
    `sex` TINYINT COMMENT "用戶性別",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用戶最後一次訪問時間",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "用戶總消費",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "用戶最大停留時間",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用戶最小停留時間"
)
ENGINE=OLAP
AGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`)
PARTITION BY RANGE(`date`)
(
    PARTITION `p201701` VALUES LESS THAN ("2017-02-01"),
    PARTITION `p201702` VALUES LESS THAN ("2017-03-01"),
    PARTITION `p201703` VALUES LESS THAN ("2017-04-01")
)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16
PROPERTIES
(
    "replication_num" = "3",
    "storage_medium" = "SSD",
    "storage_cooldown_time" = "2018-01-01 12:00:00"
);

通過Range date來分Partition,通過Hash user_id 來分了Buckets

分區和分桶

Doris支持兩層的數據劃分,第一層是Partition,支持Range和List的劃分方式。第二層是Bucket(Tablet),僅支持Hash的劃分方式。

下面我們來分別介紹下分區和分桶。

分區

  1. Partition
  • Partition 列可以指定一列或多列,分區列必須爲 KEY 列。多列分區的使用方式在後面 多列分區 小結介紹。
  • 不論分區列是什麼類型,在寫分區值時,都需要加雙引號。
  • 分區數量理論上沒有上限。
  • 當不使用 Partition 建表時,系統會自動生成一個和表名同名的,全值範圍的 Partition。該 Partition 對用戶不可見,並且不可刪改。
  • 創建分區時不可添加範圍重疊的分區。

1.1 Range分區

分區列通常爲時間列,方便管理新舊數據

Partition 支持通過 VALUES LESS THAN(...)僅指定上界,系統會將前一個分區的上界作爲該分區的下界,生成一個左閉右開的區間。同時,也支持通過 VALUES [...) 指定上下界,生成一個左閉右開的區間

示例:

PARTITION BY RANGE(`date`)
(
    PARTITION `p201701` VALUES LESS THAN ("2017-02-01"),
    PARTITION `p201702` VALUES LESS THAN ("2017-03-01"),
    PARTITION `p201703` VALUES LESS THAN ("2017-04-01")
)

這樣的建表語句後,會生成3個分區

p201701: [MIN_VALUE,  2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)

當我們增加一個分區 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)

然後再刪除分區p201703,則分區結果如下:

p201701: [MIN_VALUE,  2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

可以看到新增分區,分區的下界會緊接着上一個分區的上界,而刪除分區不會改變已存在的分區的範圍。當出現空洞時,空洞範圍內的數據是無法導入的。

1.2 List分區

分區列支持 BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR, VARCHAR 數據類型,分區值爲枚舉值。只有當數據爲目標分區枚舉值其中之一時,纔可以命中分區

示例:

PARTITION BY LIST(`city`)
(
    PARTITION `p_cn` VALUES IN ("Beijing", "Shanghai", "Hong Kong"),
    PARTITION `p_usa` VALUES IN ("New York", "San Francisco"),
    PARTITION `p_jp` VALUES IN ("Tokyo")
)

也可以支持多列分區:

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"))
)
  1. Bucket
  • 如果使用了 Partition,則DISTRIBUTED...語句描述的是數據在各個分區內的劃分規則。如果不使用 Partition,則描述的是對整個表的數據的劃分規則。
  • 分桶列可以是多列,Aggregate 和 Unique 模型必須爲 Key 列,Duplicate 模型可以是 key 列和 value 列。分桶列可以和 Partition 列相同或不同。
  • 分桶列的選擇,是在 查詢吞吐 和 查詢併發 之間的一種權衡:
    • 如果選擇多個分桶列,則數據分佈更均勻。如果一個查詢條件不包含所有分桶列的等值條件,那麼該查詢會觸發所有分桶同時掃描,這樣查詢的吞吐會增加,單個查詢的延遲隨之降低。這個方式適合大吞吐低併發的查詢場景
    • 如果僅選擇一個或少數分桶列,則對應的點查詢可以僅觸發一個分桶掃描。此時,當多個點查詢併發時,這些查詢有較大的概率分別觸發不同的分桶掃描,各個查詢之間的IO影響較小(尤其當不同桶分佈在不同磁盤上時),所以這種方式適合高併發的點查詢場景。
  • 分桶的數量理論上沒有上限
  1. Partition 和 Bucket 的數量和數據量的建議。
  • 一個表的 Tablet 總數量等於 (Partition num * Bucket num)。
  • 一個表的 Tablet 數量,在不考慮擴容的情況下,推薦略多於整個集羣的磁盤數量。
  • 單個 Tablet 的數據量理論上沒有上下界,但建議在 1G - 10G 的範圍內。如果單個 Tablet 數據量過小,則數據的聚合效果不佳,且元數據管理壓力大。如果數據量過大,則不利於副本的遷移、補齊,且會增加 Schema Change 或者 Rollup 操作失敗重試的代價(這些操作失敗重試的粒度是 Tablet)。
  • 當 Tablet 的數據量原則和數量原則衝突時,建議優先考慮數據量原則。
    在建表時,每個分區的 Bucket 數量統一指定。但是在動態增加分區時(ADD PARTITION),可以單獨指定新分區的 Bucket 數量。可以利用這個功能方便的應對數據縮小或膨脹。
  • 一個 Partition 的 Bucket 數量一旦指定,不可更改。所以在確定 Bucket 數量時,需要預先考慮集羣擴容的情況。比如當前只有 3 臺 host,每臺 host 有 1 塊盤。如果 Bucket 的數量只設置爲 3 或更小,那麼後期即使再增加機器,也不能提高併發度。
  • 舉一些例子:假設在有10臺BE,每臺BE一塊磁盤的情況下。如果一個表總大小爲 500MB,則可以考慮4-8個分片。5GB:8-16個分片。50GB:32個分片。500GB:建議分區,每個分區大小在 50GB 左右,每個分區16-32個分片。5TB:建議分區,每個分區大小在 50GB 左右,每個分區16-32個分片。

注:表的數據量可以通過 SHOW DATA 命令查看,結果除以副本數,即表的數據量

複合分區與單分區

複合分區

  • 第一級稱爲 Partition,即分區。用戶可以指定某一維度列作爲分區列(當前只支持整型和時間類型的列),並指定每個分區的取值範圍。
  • 第二級稱爲 Distribution,即分桶。用戶可以指定一個或多個維度列以及桶數對數據進行 HASH 分佈。

以下場景推薦使用複合分區

  • 有時間維度或類似帶有有序值的維度,可以以這類維度列作爲分區列。分區粒度可以根據導入頻次、分區數據量等進行評估。
  • 歷史數據刪除需求:如有刪除歷史數據的需求(比如僅保留最近N 天的數據)。使用複合分區,可以通過刪除歷史分區來達到目的。也可以通過在指定分區內發送 DELETE 語句進行數據刪除。
  • 解決數據傾斜問題:每個分區可以單獨指定分桶數量。如按天分區,當每天的數據量差異很大時,可以通過指定分區的分桶數,合理劃分不同分區的數據,分桶列建議選擇區分度大的列。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章