存儲設(shè)計——如何優(yōu)化 ClickHouse 索引(一)

Keypoint

  1. ClickHouse 索引與其他 RDMS 區(qū)別
  2. 稀疏主鍵索引及其構(gòu)建
  3. ClickHouse 索引最佳實(shí)踐

ClickHouse 的索引設(shè)計

  Whole data:     [---------------------------------------------]
  CounterID:      [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiikllllllll]
  Date:           [1111111222222233331233211111222222333211111112122222223111112223311122333]
  Marks:           |      |      |      |      |      |      |      |      |      |      |
                  a,1    a,2    a,3    b,3    e,2    e,3    g,1    h,2    i,1    i,3    l,3
  Marks numbers:   0      1      2      3      4      5      6      7      8      9      10

從文件目錄看 ClickHouse 存儲設(shè)計

/var/lib/clickhouse
- DataBase
  - Table
    - Parts all/Partition_key xxxx (分區(qū)鍵影響parts 數(shù)量)
      - checksum.txt (例如因?yàn)橥綄?dǎo)致all broken parts to remove錯誤)
      - columns.txt (列及對應(yīng)格式的數(shù)據(jù))
      - count.txt (當(dāng)前數(shù)據(jù)塊條數(shù))
      - default_compression_codec.txt(壓縮格式啡省,默認(rèn) LZ4)
      - primary.idx 主鍵索引 (可以與 ORDER BY 不同)
      - Column.bin(數(shù)據(jù)文件啊掏,壓縮后可能是 1:6,2:7,3:4....钧唐,在 Compact 模式下验辞,只有一個 bin)
      - Column.mk2 (好像都一樣大小丈屹,像是 Mark的縮寫?)

從存儲文件夾中可以看到,分級大概是
表 -> Parts -> 主鍵索引(idx)棉钧、各個列數(shù)據(jù)文件(bin)吉执、列數(shù)據(jù)對應(yīng) Mark(mk2) 及其他元數(shù)據(jù)文件。

bin 文件受主鍵排序及 ORDER BY 鍵以及插入順序所影響牲尺。

相同數(shù)據(jù)受低基數(shù)及高基數(shù)主鍵排序影響卵酪,如下所示,是數(shù)據(jù)相同但主鍵不同的表的相同 part谤碳,高基數(shù)排列的表凛澎,除 URL 列外,其他兩個列的數(shù)據(jù)文件大小均比低基數(shù)排列的表要大估蹄。但實(shí)際查詢的時候是否高基數(shù)會更快呢塑煎?打個問號。

# 高基數(shù)排列
drwxr-x--- 13 root       root             416 Nov  8 01:25 .
drwxr-x---  7 clickhouse clickhouse       224 Nov  8 01:34 ..
-rw-r-----  1 root       root             349 Nov  8 01:25 checksums.txt
-rw-r-----  1 root       root              82 Nov  8 01:25 columns.txt
-rw-r-----  1 root       root               7 Nov  8 01:25 count.txt
-rw-r-----  1 root       root              10 Nov  8 01:25 default_compression_codec.txt
-rw-r-----  1 root       root          269624 Nov  8 01:25 IsRobot.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 IsRobot.mrk2
-rw-r-----  1 root       root           75638 Nov  8 01:25 primary.idx
-rw-r-----  1 root       root       120469184 Nov  8 01:25 URL.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 URL.mrk2
-rw-r-----  1 root       root         9964518 Nov  8 01:25 UserID.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 UserID.mrk2


# 低基數(shù)排列
drwxr-x--- 13 root       root             416 Nov  8 01:34 .
drwxr-x---  8 clickhouse clickhouse       256 Nov  8 01:45 ..
-rw-r-----  1 root       root             348 Nov  8 01:34 checksums.txt
-rw-r-----  1 root       root              82 Nov  8 01:34 columns.txt
-rw-r-----  1 root       root               7 Nov  8 01:34 count.txt
-rw-r-----  1 root       root              10 Nov  8 01:34 default_compression_codec.txt
-rw-r-----  1 root       root           32717 Nov  8 01:34 IsRobot.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 IsRobot.mrk2
-rw-r-----  1 root       root           77519 Nov  8 01:34 primary.idx
-rw-r-----  1 root       root       158361024 Nov  8 01:34 URL.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 URL.mrk2
-rw-r-----  1 root       root          785254 Nov  8 01:34 UserID.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 UserID.mrk2

隱含的 Granule —— 并發(fā)的最小讀取單位

mk2 是一眼看不出內(nèi)容的文件臭蚁,不同列的文件大小(幾乎)相同最铁。

在創(chuàng)建表時經(jīng)常看到一個設(shè)置, granule=8192垮兑,但在存儲文件中似乎沒有與之相關(guān)的內(nèi)容冷尉。這個 Granule 實(shí)際上就與 mk2 綁定,而 idx 大小也和它掛鉤系枪。

ClickHouse 借由二分索引對主鍵索引數(shù)據(jù)塊進(jìn)行搜索雀哨,跳過不需要的數(shù)據(jù)組,這個組就是隱含的 Granule。

默認(rèn)一個 Granule 由 8192 行數(shù)據(jù)組成雾棺。每 8192 行就有一個主鍵索引作為數(shù)據(jù)入口膊夹。

為了把主鍵完整地放入主內(nèi)存,要求主鍵必須足夠小捌浩,因此有時候會獨(dú)立定義一個主鍵和 ORDER BY 鍵(主鍵必須是 ORDER BY 鍵的前綴)放刨。

一個 887 萬的數(shù)據(jù)主鍵索引只有 1083 個索引值。MySQL 則必須將主鍵全部索引尸饺,當(dāng)然进统,好處是它可以借助 B 樹索引到某條記錄,而在并發(fā)讀取數(shù)據(jù)時浪听, ClickHouse 則至少需要讀 8190 行螟碎。

除最后一列外,每個 Granule 的主鍵索引皆為該組合列的最小值迹栓,使之單調(diào)遞增抚芦,但未必指向具體的行。如下圖所示迈螟,UserID 與 URL 構(gòu)成的主鍵并不在同一行叉抡。

-- Granule0, Mark 0
240.923,goal://metry=10000467796a411...
-- Granule1, Mark1
4073,710,goal://dream...
image.png

標(biāo)記主鍵 idx——ClickHouse 的排除法

假設(shè)先按 UserID 再按 URL 排序,這表示 UserID 這一列的數(shù)據(jù)是 100% 按字母順序(lexicographical Ordering)單調(diào)遞增的答毫,240.923 就是所有 UserID 數(shù)據(jù)中最小的

但 URL 作為次一級褥民,只能保證在該 Granule 里是最小的,例如 Granule 0里的 goal://metry=10000467796a411洗搂,其他 Granule 不能保證消返。

但是是否意味著只能在同一個 Granule 中做排除呢?也不是耘拇,如果 Granule0-3 都是相同 UserID撵颊,那么同樣可以確認(rèn) goal://metry=10000467796a411 是這三個塊里面最小的,查詢小于這個值時惫叛,三個皆可排除倡勇。

這里你可能看到了優(yōu)化的曙光,后文將詳談嘉涌。

Mk2——數(shù)據(jù)的“指針”

-- Column.mk2 --
-- 壓縮后的數(shù)據(jù)塊位置(bin)
-- 解壓后的數(shù)據(jù)塊位置
block_offset,granule_offset
mk2

標(biāo)記文件是實(shí)際數(shù)據(jù)的“指針”妻熊,分別指向解壓前后的具體數(shù)據(jù)塊位置,前面提到 Granule 是最小并發(fā)讀取單位仑最,這里可以更明確這一概念:

  • Stage 1:ClickHouse 通過主鍵索引排除 Granule
  • Stage 2:未被排除的 Granule 根據(jù)編號在 mk2 中找到對應(yīng)的數(shù)據(jù)塊解壓獲取數(shù)據(jù)扔役,由于數(shù)據(jù)是壓縮的,解壓本身似乎暗含了按塊讀取的必然性警医。

mk2 的設(shè)計也符合列式數(shù)據(jù)庫的設(shè)計方式亿胸,方便刪除單列(主鍵除外)而不需要修改索引坯钦,需要讀取特定列的數(shù)據(jù)再讀以減少內(nèi)存占用。

而同時也說明一個常見的查詢“偷懶”習(xí)慣 SELECT * 危害之大:
越多的列被選中侈玄,則需要打開的文件解壓的數(shù)據(jù)越多婉刀,如果是一個數(shù)據(jù)量大的列(例如響應(yīng)體)勢必需要消耗更多的內(nèi)存和 CPU。

下圖是查詢某用戶的 Top 10 URL 訪問的數(shù)據(jù)讀取圖

SELECT URL, count(URL) AS Count
FROM hits_UserID_URL
WHERE UserID = 749927693
GROUP BY URL
ORDER BY Count DESC
LIMIT 10;
讀取數(shù)據(jù)

Ref: Block In ClickHouse

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拗馒,一起剝皮案震驚了整個濱河市路星,隨后出現(xiàn)的幾起案子溯街,更是在濱河造成了極大的恐慌诱桂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呈昔,死亡現(xiàn)場離奇詭異挥等,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堤尾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門肝劲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人郭宝,你說我怎么就攤上這事辞槐。” “怎么了粘室?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵榄檬,是天一觀的道長。 經(jīng)常有香客問我衔统,道長鹿榜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任锦爵,我火速辦了婚禮舱殿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘险掀。我一直安慰自己沪袭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布樟氢。 她就那樣靜靜地躺著枝恋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嗡害。 梳的紋絲不亂的頭發(fā)上焚碌,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音霸妹,去河邊找鬼十电。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鹃骂。 我是一名探鬼主播台盯,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畏线!你這毒婦竟也來了静盅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤寝殴,失蹤者是張志新(化名)和其女友劉穎蒿叠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚣常,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡市咽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抵蚊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片施绎。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贞绳,靈堂內(nèi)的尸體忽然破棺而出谷醉,到底是詐尸還是另有隱情,我是刑警寧澤冈闭,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布俱尼,位于F島的核電站,受9級特大地震影響拒秘,放射性物質(zhì)發(fā)生泄漏号显。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一躺酒、第九天 我趴在偏房一處隱蔽的房頂上張望押蚤。 院中可真熱鬧,春花似錦羹应、人聲如沸揽碘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雳刺。三九已至,卻和暖如春裸违,著一層夾襖步出監(jiān)牢的瞬間掖桦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工供汛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枪汪,地道東北人涌穆。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像雀久,于是被迫代替她去往敵國和親宿稀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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