Kylin、Druid、ClickHouse 核心技術對比

文章做者:吳建超程序員

內容來源:jackywoo.cn數據庫

 

導讀:Kylin、Druid、ClickHouse是目前主流的OLAP引擎,本文嘗試從數據模型和索引結構兩個角度,分析這幾個引擎的核心技術,並作簡單對比。在閱讀本文以前但願能對Kylin、Druid、ClickHouse有所理解。微信

01

Kylin數據模型

Kylin的數據模型本質上是將二維表(Hive表)轉換爲Cube,而後將Cube存儲到HBase表中,也就是兩次轉換。數據結構

第一次轉換,其實就是傳統數據庫的Cube化,Cube由CuboId組成,下圖每一個節點都被稱爲一個CuboId,CuboId表示固定列的數據數據集合,好比「 AB」 兩個維度組成的CuboId的數據集合等價於如下SQL的數據集合:架構

 

select A, B, sum(M), sum(N) from table group by A, B

 

第二次轉換,是將Cube中的數據存儲到HBase中,轉換的時候CuboId和維度信息序列化到rowkey,度量列組成列簇。在轉換的時候數據進行了預聚合。下圖展現了Cube數據在HBase中的存儲方式。大數據

02

Kylin索引結構

由於Kylin將數據存儲到HBase中,因此kylin的數據索引就是HBase的索引。HBase的索引是簡化版本的B+樹,相比於B+樹,HFile沒有對數據文件的更新操做。ui

HFile的索引是按照rowkey排序的聚簇索引,索引樹通常爲二層或者三層,索引節點比MySQL的B+樹大,默認是64KB。數據查找的時候經過樹形結構定位到節點,節點內部數據是按照rowkey有序的,能夠經過二分查找快速定位到目標。編碼

Kylin小結:適用於聚合查詢場景;由於數據預聚合,Kylin能夠說是最快的查詢引擎(group-by查詢這樣的複雜查詢,可能只須要掃描1條數據);kylin查詢效率取決因而否命中CuboId,查詢波動較大;HBase索引有點相似MySQL中的聯合索引,維度在rowkey中的排序和查詢維度組合對查詢效率影響巨大;因此Kylin建表須要業務專家參與。spa

03

Druid數據模型

Druid數據模型比較簡單,它將數據進行預聚合,只不過預聚合的方式與Kylin不一樣,kylin是Cube化,Druid的預聚合方式是將全部維度進行Group-by,能夠參考下圖:.net

04

Druid索引結構

Druid索引結構使用自定義的數據結構,總體上它是一種列式存儲結構,每一個列獨立一個邏輯文件(其實是一個物理文件,在物理文件內部標記了每一個列的start和offset)。對於維度列設計了索引,它的索引以Bitmap爲核心。下圖爲「city」列的索引結構:

首先將該列全部的惟一值排序,並生成一個字典,而後對於每一個惟一值生成一個Bitmap,Bitmap的長度爲數據集的總行數,每一個bit表明對應的行的數據是不是該值。Bitmap的下標位置和行號是一一對應的,因此能夠定位到度量列,Bitmap能夠說是反向索引。同時數據結構中保留了字典編碼後的全部列值,其爲正向的索引。

那麼查詢如何使用索引呢?以如下查詢爲例:

 

select site, sum(pv) from xx where date=2020-01-01 and city='bj' group by site

 

  1. city列中二分查找dictionary並找到'bj'對應的bitmap

  2. 遍歷city列,對於每個字典值對應的bitmap與'bj'的bitmap作與操做

  3. 每一個相與後的bitmap即爲city='bj'查詢條件下的site的一個group的pv的索引

  4. 經過索引在pv列中查找到相應的行,並作agg

  5. 後續計算

Druid小結:Druid適用於聚合查詢場景可是不適合有超高基維度的場景;存儲全維度group-by後的數據,至關於只存儲了KYLIN Cube的 Base-CuboID;每一個維度都有建立索引,因此每一個查詢都很快,而且沒有相似KYLIN的巨大的查詢效率波動。

05

ClickHouse索引結構(只討論MergeTree引擎)

由於Clickhouse數據模型就是普通二維表,這裏不作介紹,只討論索引結構。總體上Clickhouse的索引也是列式索引結構,每一個列一個文件。Clickhouse索引的大體思路是:首先選取部分列做爲索引列,整個數據文件的數據按照索引列有序,這點相似MySQL的聯合索引;其次將排序後的數據每隔8194行選取出一行,記錄其索引值和序號,注意這裏的序號不是行號,序號是從零開始並遞增的,Clickhouse中序號被稱做Mark’s number;而後對於每一個列(索引列和非索引列),記錄Mark’s number與對應行的數據的offset。

下圖中以一個二維表(date, city, action)爲例介紹了整個索引結構,其中(date,city)是索引列。

那麼查詢如何使用索引呢?以如下查詢爲例:

 

select count(distinct action) where date=toDate(2020-01-01) and city=’bj’

 

  1. 二分查找primary.idx並找到對應的mark's number集合(即數據block集合)

  2. 在上一步驟中的 block中,在date和city列中查找對應的值的行號集合,並作交集,確認行號集合

  3. 將行號轉換爲mark's number 和 offset in block(注意這裏的offset以行爲單位而不是byte)

  4. 在action列中,根據mark's number和.mark文件確認數據block在bin文件中的offset,而後根據offset in block定位到具體的列值。

  5. 後續計算

該實例中包含了對於列的正反兩個方向的查找過程。反向:查找date=toDate(2020-01-01) and city=’bj’數據的行號;正向:根據行號查找action列的值。對於反向查找,只有在查找條件匹配最左前綴的時候,才能剪枝掉大量數據,其它時候並不高效。

Clickhouse小結:MergeTree Family做爲主要引擎系列,其中包含適合明細數據的場景和適合聚合數據的場景;Clickhouse的索引有點相似MySQL的聯合索引,當查詢前綴元組能命中的時候效率最高,但是一旦不能命中,幾乎會掃描整個表,效率波動巨大;因此建表須要業務專家,這一點跟kylin相似。

06

小結

  • Kylin、Druid只適合聚合場景,ClickHouse適合明細和聚合場景

  • 聚合場景,查詢效率排序:Kylin > Druid > ClickHouse

  • KylinClickHouse建表都須要業務專家參與

  • KylinClickHouse查詢效率均可能產生巨大差別

  • ClickHouse在向量化方面作得的最好,Druid少許算子支持向量化、Kylin目前還不支持向量化計算。

今天的分享就到這裏,謝謝你們。

做者介紹:

吳建超,9年程序員一枚,目前專一於大數據處理和數據庫技術。


在文末分享、點贊、在看,給個三連擊唄~~

 


 

有熱門推薦👇

 

 

本文分享自微信公衆號 - 一萬小時極客(coding-Hub)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索