ClickHouse 與 MySQL 資料庫適用場景對比總結

kumfo發表於2022-03-30

目前來說,網上有很多相關的資料證明ClickHouse資料庫查詢響應速度比MySQL快上一百到幾百倍。實際上,ClickHouseMySQL具有不同的應用場景和侷限性,最近在研究這個ClickHouse打算應用於大量資料的表來做查詢的時候,踩了些坑,於是在此做個總結,用於後續做資料儲存以及處理的時候作為備忘,以及對想要用ClickHouse替換MySQL資料庫某部分資料儲存的時候做個參考。

採用 VersionedCollapsingMergeTree 引擎來做會產生修改但是不常修改的資料

本身 ClickHouse 不適合處理資料的頻繁修改以及刪除操作,對於刪除和修改會消耗大量的效能,特別是頻繁的單條資料修改。所以,通常我們看到很多資料上說資料儘量批量寫入,不管是以1000條,10000條還是多少條為一批,用以提升ClickHouse的效能。

另外,本身ClickHouse的資料寫入、修改、刪除是非同步的,對於操作寫入、修改、刪除後的資料需要做及時查詢的,不適合用ClickHouse來做儲存,且ClickHouse不支援事務,所以ClickHouse不要用於資料一致性較高的場景。

在某些場景,可能資料通常來說是不需要修改的,但是某些場景需要修改一次或者幾次,然後為了響應速度,希望切換到ClickHouse來的話,可以採用VersionedCollapsingMergeTree引擎來做資料儲存,關於這個儲存引擎,我這裡可以簡單介紹一下,具體的可以參考ClickHouse的詳細文件。

這個儲存引擎的大致原理是,通過提供一個sign和一個version標記,sign儲存的時候,值為1-1version儲存資料的版本號,具體應用於以下兩種場景的規則為:

  1. 需要刪除的情況下,重新插入這一行的資料,version保持不變,sign設定為-1,那麼資料表就會存在兩條除了sign不一樣的重複資料。然後ClickHouse會定期執行合併摺疊,把這樣兩條資料一致,但是兩條sign相加為0的資料刪掉。這裡就需要注意一點,是定時合併清除的,所以查詢的時候需要用group by之後,再做having(sign)>0)來手動排除刪除的資料。
  2. 修改的情況下,在做以上操作的同時,插入新資料,sign標記為1version在上一次的基礎上增加1即可。當然查詢的時候,也需要進行手動排除前一個版本的資料。

稀疏索引不適合用於精確查詢

在說這個稀疏索引不適合做精確查詢之前,先來說以下我說的這種精確查詢的場景:

  1. 需要根據某個加了索引的條件,比如id或者user_id來查詢當前行的資料;
  2. 需要根據某個加了索引的條件,如id或者user_id來取資料列表做分頁

ClickHouse 用的是稀疏索引,和MySQLB+樹不一樣。(關於稀疏索引和B+樹索引我這裡不做介紹,這兩個東西如果做介紹不是一時半會能解釋清楚,如果有人看到我這篇文章不瞭解的話,可以自行去先研究一下。),所以再做精確條件查詢的時候,ClickHouse掃描資料量會很大,實際響應速度並不會達到理想的狀態。

而對於ClickHouse採用了稀疏索引的情況,特別適合用group by來做查詢,經過幾次group by 之後,就能排除大量的資料,所以通常情況下最適合的場景就是用於處理統計查詢,在這種情況下,大量資料情況下響應速度比MySQL快幾十倍,幾百倍就能提現出來了。

列式資料庫不適合一次性查詢大量列

另外就是ClickHouse的列式資料庫的特性,基於以上說的,需要精確查詢的場景,一次性需要查詢大量的欄位情況下,響應速度也沒有想象的理想。就算式增加了很多個group by條件,最後由於需要掃描的列很多,在MySQL正確加索引的情況下,ClickHouse響應速度通常沒有MySQL快。

ClickHouse 查詢效果比 MySQL 穩定

具體的測試我這裡就不做多說,主要說一下場景。在兩種資料表都正確做好索引的情況下,在做2億資料列表查詢的時候,MySQL在做分頁資料查詢的時候,開始的幾頁查詢會明顯比較耗時,大概在500ms800ms不等,但是後續的的分頁查詢基本上能達到50ms80ms,這裡應該是MySQL資料預熱起了作用。但是ClickHouse基本上都是穩定在230ms300ms

總結

以目前的測試和觀察來看,如果需要做統計查詢,且資料不是頻繁修改的情況下,採用ClickHouse來儲存和處理資料查詢。如果需要頻繁修改或是做大資料列表查詢的場景,最好的方案還是用MySQL查詢,並對資料進行分表處理,得到的資料響應效能會比ClickHouse好太多。

相關文章