clickhouse總覽

簡介

Yandex在2016年6月15日開源的一個數據分析的數據庫,名字叫做ClickHouse

ClickHouse存儲層

ClickHouse從OLAP場景需求出發,定製開發了一套全新的高效列式存儲引擎,並且實現了數據有序存儲、主鍵索引、稀疏索引、數據Sharding、數據Partitioning、TTL、主備複製等豐富功能。以上功能共同爲ClickHouse極速的分析性能奠定了基礎。

列式存儲

相比於行式存儲,列式存儲在分析場景下有着許多優良的特性。

1)如前所述,分析場景中往往需要讀大量行但是少數幾個列。在行存模式下,數據按行連續存儲,所有列的數據都存儲在一個block中,不參與計算的列在IO時也要全部讀出,讀取操作被嚴重放大。而列存模式下,只需要讀取參與計算的列即可,極大的減低了IO cost,加速了查詢。

2)同一列中的數據屬於同一類型,壓縮效果顯著。列存往往有着高達十倍甚至更高的壓縮比,節省了大量的存儲空間,降低了存儲成本。

3)更高的壓縮比意味着更小的data size,從磁盤中讀取相應數據耗時更短。

4)自由的壓縮算法選擇。不同列的數據具有不同的數據類型,適用的壓縮算法也就不盡相同。可以針對不同列類型,選擇最合適的壓縮算法。

5)高壓縮比,意味着同等大小的內存能夠存放更多數據,系統cache效果更好。

官方數據顯示,通過使用列存,在某些分析場景下,能夠獲得100倍甚至更高的加速效應。

數據有序存儲

ClickHouse支持在建表時,指定將數據按照某些列進行sort by。

排序後,保證了相同sort key的數據在磁盤上連續存儲,且有序擺放。在進行等值、範圍查詢時,where條件命中的數據都緊密存儲在一個或若干個連續的Block中,而不是分散的存儲在任意多個Block, 大幅減少需要IO的block數量。另外,連續IO也能夠充分利用操作系統page cache的預取能力,減少page fault。

主鍵索引

ClickHouse支持主鍵索引,它將每列數據按照index granularity(默認8192行)進行劃分,每個index granularity的開頭第一行被稱爲一個mark行。主鍵索引存儲該mark行對應的primary key的值。

對於where條件中含有primary key的查詢,通過對主鍵索引進行二分查找,能夠直接定位到對應的index granularity,避免了全表掃描從而加速查詢。

但是值得注意的是:ClickHouse的主鍵索引與MySQL等數據庫不同,它並不用於去重,即便primary key相同的行,也可以同時存在於數據庫中。要想實現去重效果,需要結合具體的表引擎ReplacingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree實現,我們會在未來的文章系列中再進行詳細解讀。

稀疏索引

ClickHouse支持對任意列創建任意數量的稀疏索引。其中被索引的value可以是任意的合法SQL Expression,並不僅僅侷限於對column value本身進行索引。之所以叫稀疏索引,是因爲它本質上是對一個完整index granularity(默認8192行)的統計信息,並不會具體記錄每一行在文件中的位置。目前支持的稀疏索引類型包括:

  • minmax: 以index granularity爲單位,存儲指定表達式計算後的min、max值;在等值和範圍查詢中能夠幫助快速跳過不滿足要求的塊,減少IO。
  • set(max_rows):以index granularity爲單位,存儲指定表達式的distinct value集合,用於快速判斷等值查詢是否命中該塊,減少IO。
  • ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):將string進行ngram分詞後,構建bloom filter,能夠優化等值、like、in等查詢條件。
  • tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed): 與ngrambf_v1類似,區別是不使用ngram進行分詞,而是通過標點符號進行詞語分割。
  • bloom_filter([false_positive]):對指定列構建bloom filter,用於加速等值、like、in等查詢條件的執行。

數據Sharding

ClickHouse支持單機模式,也支持分佈式集羣模式。在分佈式模式下,ClickHouse會將數據分爲多個分片,並且分佈到不同節點上。不同的分片策略在應對不同的SQL Pattern時,各有優勢。ClickHouse提供了豐富的sharding策略,讓業務可以根據實際需求選用。

1) random隨機分片:寫入數據會被隨機分發到分佈式集羣中的某個節點上。

2) constant固定分片:寫入數據會被分發到固定一個節點上。

3)column value分片:按照某一列的值進行hash分片。

4)自定義表達式分片:指定任意合法表達式,根據表達式被計算後的值進行hash分片。

數據分片,讓ClickHouse可以充分利用整個集羣的大規模並行計算能力,快速返回查詢結果。

更重要的是,多樣化的分片功能,爲業務優化打開了想象空間。比如在hash sharding的情況下,JOIN計算能夠避免數據shuffle,直接在本地進行local join; 支持自定義sharding,可以爲不同業務和SQL Pattern定製最適合的分片策略;利用自定義sharding功能,通過設置合理的sharding expression可以解決分片間數據傾斜問題等。

另外,sharding機制使得ClickHouse可以橫向線性拓展,構建大規模分佈式集羣,從而具備處理海量數據的能力。

數據Partitioning

ClickHouse支持PARTITION BY子句,在建表時可以指定按照任意合法表達式進行數據分區操作,比如通過toYYYYMM()將數據按月進行分區、toMonday()將數據按照周幾進行分區、對Enum類型的列直接每種取值作爲一個分區等。

數據Partition在ClickHouse中主要有兩方面應用:

  • 在partition key上進行分區裁剪,只查詢必要的數據。靈活的partition expression設置,使得可以根據SQL Pattern進行分區設置,最大化的貼合業務特點。
  • 對partition進行TTL管理,淘汰過期的分區數據。

數據TTL

在分析場景中,數據的價值隨着時間流逝而不斷降低,多數業務出於成本考慮只會保留最近幾個月的數據,ClickHouse通過TTL提供了數據生命週期管理的能力。

ClickHouse支持幾種不同粒度的TTL:

1) 列級別TTL:當一列中的部分數據過期後,會被替換成默認值;當全列數據都過期後,會刪除該列。

2)行級別TTL:當某一行過期後,會直接刪除該行。

3)分區級別TTL:當分區過期後,會直接刪除該分區。

高吞吐寫入能力

ClickHouse採用類LSM Tree的結構,數據寫入後定期在後臺Compaction。通過類LSM tree的結構,ClickHouse在數據導入時全部是順序append寫,寫入後數據段不可更改,在後臺compaction時也是多個段merge sort後順序寫回磁盤。順序寫的特性,充分利用了磁盤的吞吐能力,即便在HDD上也有着優異的寫入性能。

官方公開benchmark測試顯示能夠達到50MB-200MB/s的寫入吞吐能力,按照每行100Byte估算,大約相當於50W-200W條/s的寫入速度。

有限支持delete、update

在分析場景中,刪除、更新操作並不是核心需求。ClickHouse沒有直接支持delete、update操作,而是變相支持了mutation操作,語法爲alter table delete where filter_expr,alter table update col=val where filter_expr

目前主要限制爲刪除、更新操作爲異步操作,需要後臺compation之後才能生效。

主備同步

ClickHouse通過主備複製提供了高可用能力,主備架構下支持無縫升級等運維操作。而且相比於其他系統它的實現有着自己的特色:

1)默認配置下,任何副本都處於active模式,可以對外提供查詢服務;

2)可以任意配置副本個數,副本數量可以從0個到任意多個;

3)不同shard可以配置不提供副本個數,用於解決單個shard的查詢熱點問題;

ClickHouse計算層

ClickHouse在計算層做了非常細緻的工作,竭盡所能榨乾硬件能力,提升查詢速度。它實現了單機多核並行、分佈式計算、向量化執行與SIMD指令、代碼生成等多種重要技術。

多核並行

ClickHouse將數據劃分爲多個partition,每個partition再進一步劃分爲多個index granularity,然後通過多個CPU核心分別處理其中的一部分來實現並行數據處理。

在這種設計下,單條Query就能利用整機所有CPU。極致的並行處理能力,極大的降低了查詢延時。

分佈式計算

除了優秀的單機並行處理能力,ClickHouse還提供了可線性拓展的分佈式計算能力。ClickHouse會自動將查詢拆解爲多個task下發到集羣中,然後進行多機並行處理,最後把結果匯聚到一起。

在存在多副本的情況下,ClickHouse提供了多種query下發策略:

  • 隨機下發:在多個replica中隨機選擇一個;
  • 最近hostname原則:選擇與當前下發機器最相近的hostname節點,進行query下發。在特定的網絡拓撲下,可以降低網絡延時。而且能夠確保query下發到固定的replica機器,充分利用系統cache。
  • in order:按照特定順序逐個嘗試下發,當前一個replica不可用時,順延到下一個replica。
  • first or random:在In Order模式下,當第一個replica不可用時,所有workload都會積壓到第二個Replica,導致負載不均衡。first or random解決了這個問題:當第一個replica不可用時,隨機選擇一個其他replica,從而保證其餘replica間負載均衡。另外在跨region複製場景下,通過設置第一個replica爲本region內的副本,可以顯著降低網絡延時。

向量化執行與SIMD

ClickHouse不僅將數據按列存儲,而且按列進行計算。傳統OLTP數據庫通常採用按行計算,原因是事務處理中以點查爲主,SQL計算量小,實現這些技術的收益不夠明顯。但是在分析場景下,單個SQL所涉及計算量可能極大,將每行作爲一個基本單元進行處理會帶來嚴重的性能損耗:

1)對每一行數據都要調用相應的函數,函數調用開銷佔比高;

2)存儲層按列存儲數據,在內存中也按列組織,但是計算層按行處理,無法充分利用CPU cache的預讀能力,造成CPU Cache miss嚴重;

3)按行處理,無法利用高效的SIMD指令;

ClickHouse實現了向量執行引擎(Vectorized execution engine),對內存中的列式數據,一個batch調用一次SIMD指令(而非每一行調用一次),不僅減少了函數調用次數、降低了cache miss,而且可以充分發揮SIMD指令的並行能力,大幅縮短了計算耗時。向量執行引擎,通常能夠帶來數倍的性能提升。

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