目前來說,網上有很多相關的資料證明ClickHouse
資料庫查詢響應速度比MySQL
快上一百到幾百倍。實際上,ClickHouse
和MySQL
具有不同的應用場景和侷限性,最近在研究這個ClickHouse
打算應用於大量資料的表來做查詢的時候,踩了些坑,於是在此做個總結,用於後續做資料儲存以及處理的時候作為備忘,以及對想要用ClickHouse
替換MySQL
資料庫某部分資料儲存的時候做個參考。
採用 VersionedCollapsingMergeTree
引擎來做會產生修改但是不常修改的資料
本身 ClickHouse
不適合處理資料的頻繁修改以及刪除操作,對於刪除和修改會消耗大量的效能,特別是頻繁的單條資料修改。所以,通常我們看到很多資料上說資料儘量批量寫入,不管是以1000條,10000條還是多少條為一批,用以提升ClickHouse
的效能。
另外,本身ClickHouse
的資料寫入、修改、刪除是非同步的,對於操作寫入、修改、刪除後的資料需要做及時查詢的,不適合用ClickHouse
來做儲存,且ClickHouse
不支援事務,所以ClickHouse
不要用於資料一致性較高的場景。
在某些場景,可能資料通常來說是不需要修改的,但是某些場景需要修改一次或者幾次,然後為了響應速度,希望切換到ClickHouse
來的話,可以採用VersionedCollapsingMergeTree
引擎來做資料儲存,關於這個儲存引擎,我這裡可以簡單介紹一下,具體的可以參考ClickHouse
的詳細文件。
這個儲存引擎的大致原理是,通過提供一個sign
和一個version
標記,sign
儲存的時候,值為1
和-1
,version
儲存資料的版本號,具體應用於以下兩種場景的規則為:
- 需要刪除的情況下,重新插入這一行的資料,
version
保持不變,sign
設定為-1
,那麼資料表就會存在兩條除了sign
不一樣的重複資料。然後ClickHouse
會定期執行合併摺疊,把這樣兩條資料一致,但是兩條sign
相加為0
的資料刪掉。這裡就需要注意一點,是定時合併清除的,所以查詢的時候需要用group by
之後,再做having(sign)>0)
來手動排除刪除的資料。 - 修改的情況下,在做以上操作的同時,插入新資料,
sign
標記為1
,version
在上一次的基礎上增加1
即可。當然查詢的時候,也需要進行手動排除前一個版本的資料。
稀疏索引不適合用於精確查詢
在說這個稀疏索引不適合做精確查詢之前,先來說以下我說的這種精確查詢的場景:
- 需要根據某個加了索引的條件,比如
id
或者user_id
來查詢當前行的資料; - 需要根據某個加了索引的條件,如
id
或者user_id
來取資料列表做分頁
ClickHouse
用的是稀疏索引,和MySQL
的B+
樹不一樣。(關於稀疏索引和B+
樹索引我這裡不做介紹,這兩個東西如果做介紹不是一時半會能解釋清楚,如果有人看到我這篇文章不瞭解的話,可以自行去先研究一下。),所以再做精確條件查詢的時候,ClickHouse
掃描資料量會很大,實際響應速度並不會達到理想的狀態。
而對於ClickHouse
採用了稀疏索引的情況,特別適合用group by
來做查詢,經過幾次group by
之後,就能排除大量的資料,所以通常情況下最適合的場景就是用於處理統計查詢,在這種情況下,大量資料情況下響應速度比MySQL
快幾十倍,幾百倍就能提現出來了。
列式資料庫不適合一次性查詢大量列
另外就是ClickHouse
的列式資料庫的特性,基於以上說的,需要精確查詢的場景,一次性需要查詢大量的欄位情況下,響應速度也沒有想象的理想。就算式增加了很多個group by
條件,最後由於需要掃描的列很多,在MySQL
正確加索引的情況下,ClickHouse
響應速度通常沒有MySQL
快。
ClickHouse
查詢效果比 MySQL
穩定
具體的測試我這裡就不做多說,主要說一下場景。在兩種資料表都正確做好索引的情況下,在做2億
資料列表查詢的時候,MySQL
在做分頁資料查詢的時候,開始的幾頁查詢會明顯比較耗時,大概在500ms
至800ms
不等,但是後續的的分頁查詢基本上能達到50ms
至80ms
,這裡應該是MySQL
資料預熱起了作用。但是ClickHouse
基本上都是穩定在230ms
至300ms
。
總結
以目前的測試和觀察來看,如果需要做統計查詢,且資料不是頻繁修改的情況下,採用ClickHouse
來儲存和處理資料查詢。如果需要頻繁修改或是做大資料列表查詢的場景,最好的方案還是用MySQL
查詢,並對資料進行分表處理,得到的資料響應效能會比ClickHouse
好太多。