ClickHouse *MergeTree表引擎
- 2019 年 10 月 6 日
- 筆記
Clickhouse 中最強大的表引擎當屬 MergeTree引擎及*MergeTree中的其他分支引擎。
MergeTree
數據是由多組part文件組成,每一個part的數據是按照主鍵進行字典序排列。這些數據片段在後台按照一定規則合併。
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, ...]
- ENGINE:表的引擎類型,MergeTree要求有一個日期欄位,還有主鍵
- PARTITION BY — 分區鍵
- ORDER BY — 排序鍵
- PRIMARY KEY — 主鍵,默認情況下主鍵跟排序鍵(由 ORDER BY 子句指定)相同
- SAMPLE BY — 用於抽樣的表達式,如果要用抽樣表達式,主鍵中必須包含這個表達式。
- SETTINGS — 影響 MergeTree 性能的額外參數 index_granularity — 索引粒度 use_minimalistic_part_header_in_zookeeper — 數據片段頭在 ZooKeeper 中的存儲方式 min_merge_bytes_to_use_direct_io — 使用直接 I/O 來操作磁碟的合併操作時要求的最小數據量,默認10G。
ReplacingMergeTree
該引擎和MergeTree的不同之處在於它會刪除具有相同主鍵的重複項。但數據的去重只會在merge的過程中出現,merge操作是後台進程非同步執行。 OPTIMIZE TABLE 操作可以手動觸發merge操作,但會引發對大量數據的讀和寫操作,降低性能。因此,ReplacingMergeTree 適用於在後台清除重複的數據以節省空間,並不保證沒有重複的數據出現。
CREATE TABLE default.t1 ( `gmt` Date, `id` UInt16, `name` String, `ver` UInt16 ) ENGINE = ReplacingMergeTree(gmt, name, 8192, ver)
合併的時候,ReplacingMergeTree 從所有具有相同主鍵的行中選擇一行留下:
- 如果 ver 列未指定,選擇最後一條。
- 如果 ver 列已指定,選擇 ver 值最大的版本。
SummingMergeTree
當合併 SummingMergeTree 表的數據片段時,ClickHouse 會把所有具有相同主鍵的行進行匯總,將同一主鍵的行替換為包含sum後的一行記錄。如果主鍵的組合方式使得單個鍵值對應於大量的行,則可以顯著的減少存儲空間並加快數據查詢的速度。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = SummingMergeTree([columns]) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...
- 如果沒有指定 [columns],ClickHouse 會把除主鍵外的其他列都進行匯總。
- 如果用於匯總的所有列中的值均為0,則該行會被刪除。
- 按片段合併數據,會出現不同數據片段中包含具有相同主鍵的行。
AggregatingMergeTree
ClickHouse會將相同主鍵的行(在一個數據片段內)替換為單個存儲一系列聚合函數狀態的行。可以使用 AggregatingMergeTree 表來做增量數據統計聚合,包括物化視圖的數據聚合。
create table visits(gmt Date, D1 String, D2 String, D3 String, M1 UInt16) ENGINE=MergeTree(gmt, (gmt, D1, D2, D3), 8192) CREATE MATERIALIZED VIEW basic ENGINE = AggregatingMergeTree() PARTITION BY toYYYYMM(StartDate) ORDER BY (CounterID, StartDate) AS SELECT CounterID, StartDate, sumState(Sign) AS Visits, uniqState(UserID) AS Users FROM visits GROUP BY CounterID, StartDate;
- AggregatingMergeTree 是在 MergeTree 基礎之上,針對聚合函數結果,作增量計算優化的一個設計。
- 不能使用普通的 INSERT 去添加數據,一是可以用 INSERT SELECT 來插入數據,二是可以創建一個物化視圖,通過物化視圖導入數據。
CollapsingMergeTree
在創建時與 MergeTree 基本一樣,除了最後多了一個參數,需要指定 Sign 位(必須是 Int8 類型)。CollapsingMergeTree 會非同步的刪除(摺疊)除了特定列 Sign 1 和 -1 值以外的所有欄位的值重複的行。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = CollapsingMergeTree(sign) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]
- sign — 類型列的名稱:1 是「狀態」行,-1 是「取消」行。
VersionedCollapsingMergeTree
是collapsingmergetree的升級,使用不同的collapsing演算法,該演算法允許使用多個執行緒以任何順序插入數據。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = VersionedCollapsingMergeTree(sign, version) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]
- sign — 類型列的名稱:1 是「狀態」行,-1 是「取消」行。
- version — 包含對象版本的列,*uint類型。
Replicated*MergeTree
只有 Replicated*MergeTree 系列裡的表可支援副本:
ReplicatedMergeTree
ReplicatedSummingMergeTree
ReplicatedReplacingMergeTree
ReplicatedAggregatingMergeTree
ReplicatedCollapsingMergeTree
ReplicatedVersionedCollapsingMergeTree
ReplicatedGraphiteMergeTree
CREATE TABLE table_name ( EventDate DateTime, CounterID UInt32, UserID UInt32 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}') PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID)- INSERT 和 ALTER 操作副本間會複製。
- CREATE,DROP,ATTACH,DETACH 和 RENAME 語句只會在單個伺服器上執行,不會被複制。
- 複製表需要藉助Zookeeper。
- 相比非複製表,寫 zk 會導致
INSERT的延遲略長一些,建議不要每秒一個INSERT,盡量批量寫入。 - 複製是多主非同步。
- 默認INSERT 語句僅等待一個副本寫入成功後返回,insert_quorum參數可以指定幾個副本寫入成功後返回,默認為0。
- 數據塊會自動去重。
GraphiteMergeTree
應用於Graphite data的數據匯總,該引擎減少了存儲容量,提高了Graphite查詢的效率。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( Path String, Time DateTime, Value <Numeric_type>, Version <Numeric_type> ... ) ENGINE = GraphiteMergeTree(config_section) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]
- config_section — 配置文件中名稱,如下graphite_rollup_example
<!-- Example of parameters for GraphiteMergeTree table engine --> <graphite_rollup_example> <pattern> <regexp>click_cost</regexp> <function>any</function> <retention> <age>0</age> <precision>3600</precision> </retention> <retention> <age>86400</age> <precision>60</precision> </retention> </pattern> <default> <function>max</function> <retention> <age>0</age> <precision>60</precision> </retention> <retention> <age>3600</age> <precision>300</precision> </retention> <retention> <age>86400</age> <precision>3600</precision> </retention> </default> </graphite_rollup_example>