【ClickHouse系列】MergeTree引擎介紹

MergeTree引擎介紹

Clickhouse 中最強大的表引擎當屬 MergeTree (合併樹)引擎及該系列(*MergeTree)中的其他引擎。

MergeTree 系列中的引擎目的在於將大量數據插入表中,數據迅速地一部分一部分寫入表中,然後在後臺通過某些規則進行數據合併。這種方法比插入期間連續重寫存儲中的數據效率更高。

特點

  • 數據存儲按主鍵排序

  • 支持數據分區

  • 支持數據複製(ReplicatedMergeTree)

  • 支持數據採樣

建表語句

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:引擎名和參數, ENGINE = MergeTree(). MergeTree 引擎沒有參數
  • PARTITION BY:分區鍵,要按月分區,可以使用表達式 toYYYYMM(date_column)
  • ORDER BY:排序鍵,例如: ORDER BY (CounterID, EventDate)
  • PRIMARY KEY:主鍵,默認情況下主鍵跟排序鍵(由 ORDER BY 子句指定)相同,大部分情況下不需要再專門指定一個 PRIMARY KEY 子句。
  • SAMPLE BY:用於抽樣的表達式。如果要用抽樣表達式,主鍵中必須包含這個表達式,例如SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))
  • SETTINGS:影響 MergeTree 性能的額外參數:
    • index_granularity:索引粒度。即索引中相鄰『標記』間的數據行數。默認值,8192 。該列表中所有可用的參數可以從這裏查看 MergeTreeSettings.h 。
    • index_granularity_bytes:索引粒度,以字節爲單位,默認值: 10Mb。如果僅按數據行數限制索引粒度, 請設置爲0(不建議)。
    • enable_mixed_granularity_parts:啓用或禁用通過 index_granularity_bytes 控制索引粒度的大小。在19.11版本之前, 只有 index_granularity 配置能夠用於限制索引粒度的大小。當從大表(數十或數百兆)中查詢數據時候,index_granularity_bytes 配置能夠提升ClickHouse的性能。如果你的表內數據量很大,可以開啓這項配置用以提升SELECT 查詢的性能。
    • use_minimalistic_part_header_in_zookeeper:數據片段頭在 ZooKeeper 中的存儲方式。如果設置了 use_minimalistic_part_header_in_zookeeper=1 ,ZooKeeper 會存儲更少的數據。
    • min_merge_bytes_to_use_direct_io:使用直接 I/O 來操作磁盤的合併操作時要求的最小數據量。合併數據片段時,ClickHouse 會計算要被合併的所有數據的總存儲空間。如果大小超過了 min_merge_bytes_to_use_direct_io 設置的字節數,則 ClickHouse 將使用直接 I/O 接口(O_DIRECT 選項)對磁盤讀寫。如果設置 min_merge_bytes_to_use_direct_io = 0 ,則會禁用直接 I/O。默認值:10 * 1024 * 1024 * 1024 字節。
    • merge_with_ttl_timeout:TTL合併頻率的最小間隔時間。默認值: 86400 (1 天)。
    • write_final_mark:啓用或禁用在數據片段尾部寫入最終索引標記。默認值: 1(不建議更改)。
    • storage_policy:存儲策略。

數據存儲方式

主鍵索引

表數據是按照主鍵順序存儲的。如果主鍵表達式中有多個列,則會先按照第一個列排序,如果第一個列中值是相同的再按照第二個列,排序方式類似MySQL的order by column1,column2產生的的結果。

分區鍵

如果表設置了分區鍵,數據會根據分區鍵插入到不同的分區,否則會都插入到一個分區中。同分區中的parts纔會進行merge操作。

每個數據邏輯上可以被看做一個顆粒,多個顆粒被存儲在一個顆粒集中,顆粒集的大小就是由上述index_granularity參數設定的,主鍵索引就是由連續的顆粒集中的首行構成的,所以這個顆粒集就是ClickHouse在select數據時的最小集合。

例如:

  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 num:  0      1      2      3      4      5      6      7      8      9      10

注:採用稀疏索引會導致在查詢數據時會多查詢2*index_granularity個數據,但是ClickHouse每個列都分別存爲一個文件,通過並行處理彌補了這一劣勢。

在查詢數據時,可以利用主鍵索引配合分區鍵作爲條件,ClickHouse會現根據分區鍵縮小範圍,再根據主鍵去查詢數據。

局部單調索引

以時間索引來說,在一個月內的天都是單調遞增有序的,但是在多個月中的天就不是有序的,如果在查詢條件中只涉及到一個月內,ClickHouse會進行分析,進而會使用索引去查詢數據,如果條件中沒有限定到一個月內,則ClickHouse會掃描全部數據。

跳數索引

這些索引是由數據塊按粒度分割後的每部分在指定表達式上彙總信息 granularity_value 組成(粒度大小用表引擎裏 index_granularity 的指定)。

CREATE TABLE table_name
(
    u64 UInt64,
    i32 Int32,
    s String,
    ...
    INDEX a (u64 * i32, s) TYPE minmax GRANULARITY 3,
    INDEX b (u64 * length(s)) TYPE set(1000) GRANULARITY 4
) ENGINE = MergeTree()
...

併發訪問

應對錶的併發訪問,我們使用多版本機制。換言之,當同時讀和更新表時,數據從當前查詢到的一組片段中讀取。沒有冗長的的鎖。插入不會阻礙讀取。

對錶的讀操作是自動並行的。

列和表的TTL

TTL可以設置值的生命週期,它既可以爲整張表設置,也可以爲每個列字段單獨設置。如果TTL同時作用於表和字段,ClickHouse會使用先到期的那個。

列字段TTL

當列字段中的值過期時,ClickHouse會將它們替換成數據類型的默認值。如果分區內,某一列的所有值均已過期,則ClickHouse會從文件系統中刪除這個分區目錄下的列文件。

TTL子句不能被用於主鍵字段。例如:

CREATE TABLE example_table
(
    d DateTime,
    a Int TTL d + INTERVAL 1 MONTH,
    b Int TTL d + INTERVAL 1 MONTH,
    c String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d;

注:列字段如果過期部分被刪掉。在查詢時返回的是數據類型字符串,在處理數據時需注意,建議少用這種設置

表 TTL

當表內的數據過期時,ClickHouse會刪除所有對應的行。例如:

CREATE TABLE example_table
(
    d DateTime,
    a Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d
TTL d + INTERVAL 1 MONTH;

數據刪除

ClickHouse沒有刪除功能,數據刪除大體有兩種方式:TTL過期刪除和手動刪除partition。TTL過期刪除是在merge數據塊時進行的,如果在merge時執行查詢有可能查到過期數據,此時可以提前執行OPTIMIZE來避免這種情況。手動刪除就是直接刪掉所有指定分區文件,數據直接被刪掉了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章