1. 程式人生 > 實用技巧 >ClickHouse MergeTree引擎的簡單介紹

ClickHouse MergeTree引擎的簡單介紹

1.介紹
Clickhouse 中最強大的表引擎當屬 MergeTree (合併樹)引擎及該系列(MergeTree)中的其他引擎。MergeTree 允許依據主鍵和日期建立索引,並進行實時的資料更新操作。MergeTree 是 ClickHouse 裡最為先進的表引擎。

請注意不要將 MergeTree 跟 Merge引擎混淆!!!

MergeTree 引擎系列的基本理念如下。當你有巨量資料要插入到表中,你要高效地一批批寫入資料片段,並希望這些資料片段在後臺按照一定規則合併。相比在插入時不斷修改(重寫)資料進儲存,這種策略會高效很多。

主要特點:

儲存的資料按主鍵排序。
這讓你可以建立一個用於快速檢索資料的小稀疏索引。
允許使用分割槽,如果指定了分割槽鍵的話。
在相同資料集和相同結果集的情況下 ClickHouse 中某些帶分割槽的操作會比普通操作更快。查詢中指定了分割槽鍵時 ClickHouse 會自動擷取分割槽資料。這也有效增加了查詢效能。
支援資料副本。
ReplicatedMergeTree 系列的表便是用於此。更多資訊,請參閱官方文件。
支援資料取樣。
需要的話,你可以給表設定一個取樣方法。

不使用取樣表示式的例子:

MergeTree(EventDate, (CounterID, EventDate), 8192)*

使用取樣表示式的例子:
 MergeTree(EventDate, intHash32(UserID), (CounterID, EventDate, intHash32(UserID)), 8192)*


2. 建表

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
    INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

MergeTree 引擎在建立時接收以下4個引數,

日期欄位的名稱 (索引欄位)
取樣表示式 (可選的)
含有主鍵相關欄位的元組
稀疏索引的粒度(見下文)。
以 MergeTree 作為引擎的資料表必須含有一個獨立的 Date 欄位。比如說, EventDate 欄位。這個日期欄位必須是 Date 型別的(非 DateTime 型別)。

主鍵可以是任意表達式構成的元組(通常是列名稱的元組),或者是單獨一個欄位。

抽樣表示式(可選的)可以是任意表達式。這個表示式必須在主鍵中。上面的例子使用了 CounterID 的雜湊 intHash32 作為取樣表示式,旨在近乎隨機地在 CounterID 和 EventDate 內打亂資料條目。換而言之,當我們在查詢中使用 SAMPLE 子句時,我們就可以得到一個近乎隨機分佈的使用者列表。

資料表將資料分割為小的索引塊作為單位進行處理。 每個索引塊之間依照主鍵排序。每個索引塊記錄了指定的開始日期和結束日期。在您插入資料時,MergeTree 就會對資料進行排序處理,以保證儲存在索引塊內的資料有序。 索引塊之間的合併過程會在系統後臺定期自動執行。MergeTree 引擎會選擇幾個相鄰的索引塊進行合併(通常是較小的索引塊), 然後對二者合併、排序。

具體而言, 向 MergeTree 表中插入資料時,引擎會首先對新資料執行遞增排序而儲存索引塊;其後,資料索引塊之間又會進一步合併,以減少總體索引塊數量。 因此,合併過程本身並無過多排序工作。

3.主鍵和索引在查詢中的表現
我們以 (CounterID, Date) 以主鍵。排序好的索引的圖示會是下面這樣:

全部資料  :     [-------------------------------------------------------------------------]
CounterID:      [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiikllllllll]
Date:           [1111111222222233331233211111222222333211111112122222223111112223311122333]
標記:            |      |      |      |      |      |      |      |      |      |      |
                a,1    a,2    a,3    b,3    e,2    e,3    g,1    h,2    i,1    i,3    l,3
標記號:          0      1      2      3      4      5      6      7      8      9      10

如果指定查詢如下:

CounterID in (‘a’,’h’),伺服器會讀取標記號在 [0, 3) 和 [6, 8) 區間中的資料。
CounterID IN (‘a’,’h’) AND Date = 3,伺服器會讀取標記號在 [1, 3) 和 [7, 8) 區間中的資料。
Date = 3,伺服器會讀取標記號在 [1, 10] 區間中的資料。
上面例子可以看出使用索引通常會比全表描述要高效。

稀疏索引會引起額外的資料讀取。當讀取主鍵單個區間範圍的資料時,每個資料塊中最多會多讀 index_granularity * 2 行額外的資料。大部分情況下,當 index_granularity = 8192 時,ClickHouse的效能並不會降級。

稀疏索引讓你能操作有巨量行的表。因為這些索引是常駐記憶體(RAM)的。

ClickHouse 不要求主鍵惟一。所以,你可以插入多條具有相同主鍵的行。