ClickHouse | MergeTree引擎之?dāng)?shù)據(jù)分區(qū)
前言
前面通過?一文了解ClickHouse ?介紹過ClickHouse,特性,結(jié)構(gòu),使用場(chǎng)景。自己并未完全深入學(xué)習(xí)clickhouse,因?yàn)楣敬蛩阈》秶褂肅lickHouse,所以有必要深入學(xué)習(xí)之。本文了解 Clickhouse 的分區(qū)感念 和 分區(qū)合并規(guī)則。
MergeTree數(shù)據(jù)分區(qū)規(guī)則
創(chuàng)建按照月份為分區(qū)條件的表?tab_partition
CREATE?TABLE?tab_partition(`dt`?Date,?`v`?UInt8)?
ENGINE?=?MergeTree?PARTITION?BY?toYYYYMM(dt)?ORDER?BY?v;
insert?into?tab_partition(dt,v)?values?('2020-02-11',1),('2020-02-13',2);
insert?into?tab_partition(dt,v)?values?('2020-04-11',3),('2020-04-13',4);
insert?into?tab_partition(dt,v)?values?('2020-09-11',5),('2020-09-10',6);
insert?into?tab_partition(dt,v)?values?('2020-10-12',7),('2020-10-09',8);
insert?into?tab_partition(dt,v)?values?('2020-02-14',9),('2020-02-15',10);
insert?into?tab_partition(dt,v)?values?('2020-02-11',23),('2020-02-13',45);
MergeTree 存儲(chǔ)引擎在寫入數(shù)據(jù)之后生成對(duì)應(yīng)的分區(qū)文件為:

MergeTree數(shù)據(jù)分區(qū)目錄命名規(guī)則 其規(guī)則為
PartitionID_MinBlockNum_MaxBlockNum_Level
比如?202002_4_4_0?其中 202002 是分區(qū)ID ,4_4?對(duì)應(yīng)的是
最小的數(shù)據(jù)塊編號(hào)和最大的數(shù)據(jù)塊編號(hào),最后的_0 表示目前分區(qū)合并的層級(jí)。
各部分的含義及命名規(guī)則如下:
PartitionID:該值由 insert 數(shù)據(jù)時(shí)分區(qū)鍵的值來決定。分區(qū)鍵支持使用任何一個(gè)或者多個(gè)字段組合表達(dá)式,針對(duì)取值數(shù)據(jù)類型的不同,分區(qū)ID的生成邏輯目前有四種規(guī)則:
不指定分區(qū)鍵:如果建表時(shí)未指定分區(qū)鍵,則分區(qū)ID默認(rèn)使用all,所有數(shù)據(jù)都被寫入all分區(qū)中
整型字段:如果分區(qū)鍵取值是整型字段,并且無(wú)法轉(zhuǎn)換為YYYYMMDD的格式,則會(huì)按照該整型字段的字符形式輸出,作為分區(qū)ID取值
日期類型:如果分區(qū)鍵屬于日期格式,或可以轉(zhuǎn)換為YYYYMMDD格式的整型,則按照YYYYMMDD格式化后的字符形式輸出,作為分區(qū)ID取值
其他類型:如果使用其他類似Float、String等類型作為分區(qū)鍵,會(huì)通過對(duì)其插入數(shù)據(jù)的128位Hash值作為分區(qū)ID的取值
MinBlockNum 和 MaxBlockNum: BlockNum 是一個(gè)整型的自增長(zhǎng)型編號(hào),該編號(hào)在單張MergeTree表中從1開始全局累加,當(dāng)有新的分區(qū)目錄創(chuàng)建后,該值就加1,對(duì)新的分區(qū)目錄來講,MinBlockNum 和 MaxBlockNum 取值相同。例如上面示例數(shù)據(jù)為202002_1_1_0??202002_1_5_1,但當(dāng)分區(qū)目錄進(jìn)行合并后,取值規(guī)則會(huì)發(fā)生變化, MinBlockNum 取同一分區(qū)所欲目錄中最新的 MinBlockNum值。MaxBlockNum 取同一分區(qū)內(nèi)所有目錄中的最大值。
Level: 表示合并的層級(jí)。相當(dāng)于某個(gè)分區(qū)被合并的次數(shù),它不是以表全局累加,而是以分區(qū)為單位,初始創(chuàng)建的分區(qū),初始值為0,相同分區(qū)ID發(fā)生合并動(dòng)作時(shí),在相應(yīng)分區(qū)內(nèi)累計(jì)加1。
MergeTree數(shù)據(jù)分區(qū)合并規(guī)則
隨著數(shù)據(jù)的寫入MergeTree 存儲(chǔ)引擎會(huì)很多分區(qū)目錄。如果分區(qū)目錄數(shù)太多怎么辦?
因?yàn)镃lickhouse 的MergeTree 存儲(chǔ)引擎是基于 LSM 實(shí)現(xiàn)的。MergeTree可以通過分區(qū)合并將屬于相同分區(qū)的多個(gè)目錄合并為一個(gè)新的目錄(官方描述在10到15分鐘內(nèi)會(huì)進(jìn)行合并,也可直接執(zhí)行optimize語(yǔ)句),已經(jīng)存在的舊目錄(也即system.parts表中activie為0的分區(qū))在之后某個(gè)時(shí)刻通過后臺(tái)任務(wù)刪除(默認(rèn)8分鐘).
分區(qū)合并
我們回顧之前創(chuàng)建的表的分區(qū)目錄
#?ls?
202002_1_1_0??202004_2_2_0??202009_3_3_0
202002_4_4_0??202002_5_5_0??
手工觸發(fā)分區(qū)合并
qabb-qa-ch00?:)?optimize?table?tab_partition;
OPTIMIZE?TABLE?tab_partition
Ok.
0?rows?in?set.?Elapsed:?0.003?sec.
qabb-qa-ch00?:)?select?partition,name,part_type,?active?from?system.parts?where??table?='tab_partition';
┌─partition─┬─name─────────┬─part_type─┬─active─┐
│?202002????│?202002_1_1_0?│?Wide??????│??????0?│
│?202002????│?202002_1_5_1?│?Wide??????│??????1?│
│?202002????│?202002_4_4_0?│?Wide??????│??????0?│
│?202002????│?202002_5_5_0?│?Wide??????│??????0?│
│?202004????│?202004_2_2_0?│?Wide??????│??????1?│
│?202009????│?202009_3_3_0?│?Wide??????│??????1?│
└───────────┴──────────────┴───────────┴────────┘
6?rows?in?set.?Elapsed:?0.003?sec.
其中 active 為1表示經(jīng)過合并之后的最新分區(qū),為0 則表示舊分區(qū),查詢時(shí)會(huì)自動(dòng)過濾 active=0 的分區(qū)。
我們通過 分區(qū) 202002 最新的分區(qū)目錄202002_1_5_1?看到合并分區(qū)新目錄的命名規(guī)則如下:
PartitionID:分區(qū)ID保持不變
MinBlockNum:取同一個(gè)分區(qū)內(nèi)所有目錄中最小的MinBlockNum值
MaxBlockNUm:取同一個(gè)分區(qū)內(nèi)所有目錄中最大的MaxBlockNum值
Level:取同一個(gè)分區(qū)內(nèi)最大Level值并加1
合并之后的目錄結(jié)構(gòu)如下:

小結(jié)
本文可以認(rèn)為是《ClickHouse 原理解析與應(yīng)用實(shí)踐》的學(xué)習(xí)筆記 ^_^。通過案例介紹了 MergeTree的分區(qū)產(chǎn)生的機(jī)制,命名規(guī)則,以及合并的基本過程。有興趣的朋友可以自己動(dòng)手實(shí)踐一下。
往期推薦
