天天看點

ClickHouse為何如此之快?

老闆:"你聽說過ClickHouse嗎?簡稱叫CK!!!"

我:"聽說過,不是個内褲品牌嗎?誰沒聽說過?你想幹什麼?!!"

老闆:"不是内褲!!是 CH !! 是一款OLAP資料庫,給你看,這是它的測試報告"

我:"假的吧,單機性能就這麼高?怎麼可能!!!"

老闆:"不信你自己試試!!"

一番搗鼓之後

我:"。。。。。。。"

颠覆三觀、陷入無限思考,心中隻有三個字:

這是什麼鬼!!

上述是我的一段親身經曆。

很多初識CH的人,内心都會經曆這麼幾個階段:

相遇,會被它那驚歎的性能所吸引;

疑惑,開始質疑它的真實性;

困惑,在親自論證了可靠性後,身體雖然是相信了,但内心依然覺得不可思議,不明就裡。

于是乎,為什麼ClickHouse這麼快? 漸漸成了一個不解之謎。

作為一個擁有ClickHouse信仰标簽的忠實粉絲,我自然也是追尋謎底的一份子。在我苦苦尋覓許久之後,今天,終于被我找到了答案。是以特地拿來與各位分享,謎底就在下面:

翻譯過來的意思是:

這是純魔法,是由前蘇聯科學家提供的技術.他們曾經用來制造火箭.

看到沒?! 這就是ClickHouse的黑魔法。

好吧,這其實是我今天剛看到的一則笑話,來自于中科院計算所博士,鄭天祺 (Amos Bird),同時他也是一名ClickHouse的Committer。

雖然剛才的謎底是假的,但疑問是真真切切存在的,為什麼ClickHouse這麼快?

已經有很多人,對這個問題做出過科學合理的解釋。

比如有人說,因為ClickHouse是列存資料庫,是以快;

也有人說,因為ClickHouse使用了向量化引擎,是以快。

這些解釋都站得住腳,但是依然不能消除我的疑問。因為這些技術并不是秘密,世面上有很多資料庫同樣使用了這些技術,但是依然被ClickHouse秒殺呀?

是以,今天我想從另外一個角度,來探讨一下ClickHouse的黑魔法,它到底是什麼。

要找到問題的謎底,其實有一個很簡單的辦法,那就是聽聽作者們自己是怎麼說的呗。

畫外音:"說的輕巧,去哪裡找作者傾訴呢?"

是以說,勤奮的人們總是容易被幸運眷顧,你看這不:

恰好,在2019的年末,在北京舉行了 中國大資料技術大會(BDTC 2019);

恰好又,這個大會邀請了 ClickHouse項目的創始人兼開源社群創始人,Alexey Milovidov;

恰恰好又,Alexey Milovidov 在大會上做了一次主題分享;

恰恰恰好又,這個分享主題就叫做 The Secrets of ClickHouse Performance Optimizations。

各位說說,怎麼就這麼巧呢?簡直做夢都要笑醒的節奏啊。

既然作者已經做了分享,那我就從這次分享出發,對ClickHouse的黑魔法做一番分析總結吧。(文末會附上Alexey Milovidov的分享視訊)

開篇伊始,Alexey Milovidov就抛出了一個靈魂的質問:

做設計的原則,到底應該是 自頂向下 的去設計,還是應該 自下而上 的去設計 ?

在傳統觀念中,或者說在我的觀念中,自然是 自頂向下的,做架構設計首先自然做的是頂層設計:

  • 事先應該做高層次的抽象設計;
  • 規劃好各個子產品的職責、切分的界面;
  • 配置設定好工程結構、包結構,最好能再來一些設計圖,等等。

而ClickHouse的設計,則采用了 自下而上。

ClickHouse的原型系統早在2008年就誕生了(有機會可以專門寫一篇,聊聊關于ClickHouse的誕生曆程),

在誕生之初,它并沒有宏偉的規劃。相反,它的目的很單純,就是希望能以最快的速度進行GROUP BY查詢和過濾。

他們是如何實踐 自下而上 設計的呢?

着眼硬體,先想後做

從硬體功能層面着手設計,在設計伊始,就至少需要想清楚這麼幾個問題:

  1. 我們将要使用的硬體水準是怎樣的?包括CPU、記憶體、硬碟、網絡等等;
  2. 在這樣的硬體上,我們需要達到怎樣的性能?包括延遲、吞吐量等等;
  3. 我們準備使用怎樣的資料結構?包括String、HashTable、Vector等等;
  4. 選擇的這些資料結構,在我們的硬體上會如何工作?

如果你能想清楚上面的問題,那麼在動手實作功能之前,就已經能夠計算出粗略的性能了。

是以,基于将硬體功效最大化的目的,ClickHouse會在記憶體中進行GROUP BY,并且使用HashTable裝載資料。

于此同時,他們非常在意CPU L3級别的緩存,因為一次L3 cache miss會帶來70~100納秒的延遲。

這意味着,在單核CPU上,它會浪費4000萬/每秒的運算;而在一個32線程的CPU上,則可能會浪費5億/每秒的運算。

是以别小看這些細節,一點一滴的将它們累加起來,資料是非常可觀的。也正因為注意了這些細節,是以ClickHouse在基準查詢中,能做到1.75億/每秒的資料掃描性能。

算法在前,抽象在後

最近常聽人念叨,"有時候,選擇比努力更重要"。 确實,路線選錯了,再努力也是白搭。

在ClickHouse的底層實作中,經常會面對這些場景:

字元串子串查詢;

數組排序;

使用HashTable等。

如何才能在實作性能的最大化呢?算法的選擇是重中之重!!!

以字元串為例,有一本專門講解字元串搜尋的書,叫做 "Handbook of Exact String Matching Algorithms",這本書列舉了35種常見的字元串搜尋算法,你猜ClickHouse使用了其中的哪一種?

一種都沒用!! 為什麼?因為性能不夠快。

在字元串搜尋方面,針對不同的場景,ClickHouse最終選擇了這些算法:

對于常量,使用Volnitsky算法;

對于非常量,使用CPU的向量化執行SIMD,暴力優化;

正則比對使用re2和hyperscan算法。

勇于嘗鮮,不行就換

除了字元串之外,其餘的場景也與它類似,ClickHouse會使用最合适、最快的算法。

如果世面上出現了,号稱性能強大的新算法,他也會将其納入,進行驗證。如果效果可行,就保留使用;如果性能不盡人意,就将其抛棄。

特定場景,特殊優化

針對在同一個場景的,不同的狀況,選擇使用不同的實作方式,盡可能的将性能最大化。關于這一點,其實在剛才介紹字元串查詢時候,針對不同場景選擇不同的算法就能展現了。

類似的例子還有很多,例如去重計數uniqCombined函數,根據資料量的不同會選擇不同的算法。當資料量較小的時候,會選擇Array儲存;當資料量中等時候,則會選擇HashSet;而當資料量很大的時候,則使用HyperLogLog算法。

包括對于資料結構比較清晰的場景,會通過代碼生成技術,實作循環展開,以減少循環次數。

還包括大家熟知的大殺器,向量化執行了。SIMD被廣泛的應用于文本轉換、資料過濾、資料解壓和JSON轉換等場景。利用寄存器暴力優化,相較于單純的使用CPU而言,也算是一種降維打擊了。

持續測試,持續改進

如果隻是單純的,在上述的細節上下功夫,還不足以建構出如此強大的ClickHouse,這裡還需要擁有一個能夠持續驗證、持續改進的機制。

由于Yandex的天然優勢,ClickHouse經常會使用真實的資料做測試,這一點很好的保證了測試場景的真實性。于此同時,ClickHouse也是我見過發版速度最快的開源軟體了,差不多每個月都能釋出一個版本,沒有一個可靠的持續內建環境,這一點也是做不到的。

也正因為擁有這樣的發版頻率,他們能夠快速疊代、快速改進。

好了,上述這些,就是我對Alexey Milovidov這次分享的一些總結和個人了解了。

最後,就以ClickHouse的口号,作為結束吧:

The ClickHouse Style:

As efficient as possible

As fast as possible

正如口号所言,他們做到了。

是以,ClickHouse的黑魔法并不是一項單一的技術,而是一種自底向上的,追求極緻性能的設計思路。