clickhouse使用一些優(yōu)化和經(jīng)驗(yàn)

一些經(jīng)驗(yàn)

1,查詢強(qiáng)烈要求帶上分區(qū)鍵過濾和主鍵過濾,如 where day = today() and itime = now()。

2,建表的時(shí)候,選擇合適的分區(qū)鍵和排序鍵是優(yōu)化的關(guān)鍵。

3,如果不允許重復(fù)主鍵(且不要求去重時(shí)效性),建議使用表類型:ReplicatedReplacingMergeTree 建表語(yǔ)句可參考https://clickhouse.yandex/docs/en/operations/table_engines/replacingmergetree/ ,注意只能保證單節(jié)點(diǎn)的數(shù)據(jù)不重復(fù),無(wú)法保證集群的。

4,如果要對(duì)某一列過濾,且該列非partition key和orderby key, 且該列過濾前后數(shù)據(jù)量差異較大,建議使用prewhere clause過濾。參考:https://clickhouse.yandex/docs/en/query_language/select/#prewhere-clause。

5,日期和時(shí)間使用Date, DateTime類型,不要用String類型。

6,建表時(shí),強(qiáng)烈建議低基數(shù)(基數(shù)小于10000)且類型為String的列,使用LowCardinality特性,例如國(guó)家(country),操作系統(tǒng)(os)皆可用LowCardinality。查詢效益提高可以40~50%,具體參考https://altinity.com/blog/2019/3/27/low-cardinality。

7,為了使復(fù)雜查詢盡量本地完成,提前減小數(shù)據(jù)量和網(wǎng)絡(luò)傳輸,加快查詢速度,創(chuàng)建分布式表時(shí),盡量按照主鍵hash分shard。例如欲加快select count(distinct uid) from table_all group by country, os的查詢速度. 創(chuàng)建分布式表table_all時(shí),shard key為cityHash64(country, os),hash函數(shù)參考https://clickhouse.tech/docs/en/sql-reference/functions/hash-functions/。

8,計(jì)算不同維度組合的指標(biāo)值時(shí),用with rollup或with cube替代union all子句。

9,建表時(shí),請(qǐng)遵守命名規(guī)范:分布式表名 = 本地表名 + 后綴"_all"。 select請(qǐng)直接操作分布式表。

10,官方已經(jīng)指出Nullable類型幾乎總是會(huì)拖累性能,因?yàn)榇鎯?chǔ)Nullable列時(shí)需要?jiǎng)?chuàng)建一個(gè)額外的文件來存儲(chǔ)NULL的標(biāo)記,并且Nullable列無(wú)法被索引。因此除非極特殊情況,應(yīng)直接使用字段默認(rèn)值表示空,或者自行指定一個(gè)在業(yè)務(wù)中無(wú)意義的值(例如用-1表示沒有商品ID)

11,稀疏索引不同于mysql的B+樹,不存在最左的原則,所以在ck查詢的時(shí)候,where條件中,基數(shù)較大的列(即區(qū)分度較高的列)在前,基數(shù)較小的列(區(qū)分度較低的列)在后。

12,多表Join時(shí)要滿足小表在右的原則,右表關(guān)聯(lián)時(shí)被加載到內(nèi)存中與左表進(jìn)行比較

13,多維分析, 查詢列不宜過多, 過濾條件帶上分區(qū)篩選 (select dim1, dim2, agg1(xxx), agg2(xxx) from table where xxxx group by dim1, dim2 )

14,禁止SELECT *, 不能拉取原始數(shù)據(jù)!!!! (clickhouse不是數(shù)據(jù)倉(cāng)庫(kù), 純粹是拉原始表數(shù)據(jù)的查詢應(yīng)該禁止,如 select a, b, c, f, e, country from xxx )

分區(qū)鍵和排序鍵

分區(qū)鍵和排序鍵理論上不能修改,在建表建庫(kù)的時(shí)候盡量考慮清楚。

0,事實(shí)表必須分區(qū),分區(qū)粒度根據(jù)業(yè)務(wù)特點(diǎn)決定,不宜過粗或過細(xì)。我們當(dāng)前都是按天分區(qū),按小時(shí)、周、月分區(qū)也比較常見(系統(tǒng)表中的query_log、trace_log表默認(rèn)就是按月分區(qū)的)。

1,分區(qū)鍵能過濾大量數(shù)據(jù),分區(qū)鍵建議使用toYYYYMMDD()按天分區(qū),如果數(shù)據(jù)量很少,100w左右,建議使用toYYYYMM()按月分區(qū),過多的分區(qū)會(huì)占用大量的資源,會(huì)對(duì)集群的穩(wěn)定性造成很大的影響。

2,分區(qū)鍵必須使用date和datetime字段,避免string類型的分區(qū)鍵

3,每個(gè)sql必須要用分區(qū)鍵,否則會(huì)導(dǎo)致大量的數(shù)據(jù)被讀取,到了集群的內(nèi)存限制直接拒絕

4,排序鍵也是一個(gè)非常重要的過濾條件,考慮到ck是OLAP 庫(kù),排序鍵默認(rèn)也是ck的主鍵,loap庫(kù)建議分區(qū)鍵要使用基數(shù)比較少的字段,比如country就比timestramp要好。

5,不要使用過長(zhǎng)的分區(qū)鍵,主鍵 。

6,CK的索引非MySQL的B樹索引,而是類似Kafka log風(fēng)格的稀疏索引,故不用考慮最左原則,但是建議基數(shù)較大的列(即區(qū)分度較高的列)在前,基數(shù)較小的列(區(qū)分度較低的列)在后。另外,基數(shù)特別大的列(如訂單ID等)不建議直接用作索引。

分區(qū)數(shù)

分區(qū)數(shù)過多會(huì)導(dǎo)致一些致命的集群?jiǎn)栴}。不建議分區(qū)數(shù)粒度過細(xì),不建議分區(qū)數(shù)過多,經(jīng)驗(yàn)來看,10億數(shù)據(jù)建議1-10個(gè)分區(qū)差不多了,當(dāng)然需要參考你的硬件資源如何。

1,select 查詢性能降低,分區(qū)數(shù)過多會(huì)導(dǎo)致打開大量文件句柄,影響集群。

2,分區(qū)數(shù)過多會(huì)導(dǎo)致集群重啟變慢,zk壓力變大,insert變慢等問題。

https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/custom-partitioning-key/

image2021-7-13_9-26-37.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容