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 不要求主鍵惟一。所以,你可以插入多條具有相同主鍵的行。