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>

Tags: