clickhouse優(yōu)化最佳實踐(易企秀)

clickhouse在易企秀數(shù)據(jù)倉庫項目中已投入使用兩年汽纤,主要為內(nèi)部用戶提供快速查詢和多維分析的能力动猬;希望你在業(yè)務(wù)當(dāng)中遇到的性能問題,在這里都能得到解決

Clickhouse堪稱OLAP領(lǐng)域的黑馬,最近發(fā)布的幾個版本在多表關(guān)聯(lián)分析上也有了極大的性能提升绅项,尤其是還引入了MaterializeMySQL Database Engine做到了實時對齊業(yè)務(wù)線mysql中的數(shù)據(jù)。

表優(yōu)化

數(shù)據(jù)類型

  • 建表時能用數(shù)值型或日期時間型表示的字段比肄,就不要用字符串——全String類型在以Hive為中心的數(shù)倉建設(shè)中常見快耿,但CK環(huán)境不應(yīng)受此影響。

  • 雖然clickhouse底層將DateTime存儲為時間戳Long類型芳绩,但不建議直接存儲Long類型掀亥,因為DateTime不需要經(jīng)過函數(shù)轉(zhuǎn)換處理,執(zhí)行效率高妥色、可讀性好搪花。

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

  • 數(shù)值類型分組最快,在新版本中ck會對string類型進(jìn)行一次hash映射再分組

分區(qū)和索引

  • 分區(qū)粒度根據(jù)業(yè)務(wù)特點決定许师,不宜過粗或過細(xì)房蝉。一般選擇按天分區(qū),也可指定為tuple()枯跑;以單表1億數(shù)據(jù)為例惨驶,分區(qū)大小控制在10-30個為最佳。
PARTITION BY tuple() 
  • 必須指定索引列敛助,clickhouse中的索引列即排序列粗卜,通過order by指定,一般在查詢條件中經(jīng)常被用來充當(dāng)篩選條件的屬性被納入進(jìn)來纳击;可以是單一維度续扔,也可以是組合維度的索引;通常需要滿足高基列在前焕数、查詢頻率大的在前原則纱昧;還有基數(shù)特別大的不適合做索引列,如用戶表的userid字段堡赔;通常篩選后的數(shù)據(jù)滿足在百萬以內(nèi)為最佳识脆。

表參數(shù)

  • index_granularity 是用來控制索引粒度的 默認(rèn)是8192,如非必須不建議調(diào)整。

  • 如果表中不是必須保留全量歷史數(shù)據(jù)灼捂,建議指定TTL离例,可以免去手動過期歷史數(shù)據(jù)的麻煩。TTL也可以通過ALTER TABLE語句隨時修改悉稠。

查詢優(yōu)化

單表查詢

  • 使用prewhere替代where關(guān)鍵字宫蛆;當(dāng)查詢列明顯多于篩選列時使用prewhere可十倍提升查詢性能
# prewhere 會自動優(yōu)化執(zhí)行過濾階段的數(shù)據(jù)讀取方式,降低io操作
select * from work_basic_model  where product='tracker_view' and ( id='eDf8fZky' or code='eDf8fZky' ) 
#替換where關(guān)鍵字
select * from work_basic_model  prewhere product='tracker_view' and ( id='eDf8fZky' or code='eDf8fZky' ) 

  • 數(shù)據(jù)采樣的猛,通過采用運(yùn)算可極大提升數(shù)據(jù)分析的性能
SELECT
    Title,
    count() * 10 AS PageViews
FROM hits_distributed
SAMPLE 0.1   #代表采樣10%的數(shù)據(jù)耀盗,也可以是具體的條數(shù)
WHERE
    CounterID = 34
GROUP BY Title
ORDER BY PageViews DESC LIMIT 1000

采樣修飾符只有在mergetree engine表中才有效,且在創(chuàng)建表時需要指定采樣策略卦尊;

  • 數(shù)據(jù)量太大時應(yīng)避免使用select * 操作叛拷,查詢的性能會與查詢的字段大小和數(shù)量成線性變換;字段越少猫牡,消耗的io資源就越少胡诗,性能就會越高。

  • 千萬以上數(shù)據(jù)集進(jìn)行order by查詢時需要搭配where條件和limit語句一起使用

  • 如非必須不要在結(jié)果集上構(gòu)建虛擬列淌友,虛擬列非常消耗資源浪費(fèi)性能,可以考慮在前端進(jìn)行處理骇陈,或者在表中構(gòu)造實際字段進(jìn)行額外存儲震庭。
select id ,pv, uv , pv/uv rate 
  • 使用 uniqCombined 替代 distinct 性能可提升10倍以上,uniqCombined 底層采用類似HyperLogLog算法實現(xiàn)你雌,如能接收2%左右的數(shù)據(jù)誤差器联,可直接使用這種去重方式提升查詢性能。

  • 對于一些確定的數(shù)據(jù)模型婿崭,可將統(tǒng)計指標(biāo)通過物化視圖的方式進(jìn)行構(gòu)建拨拓,這樣可避免數(shù)據(jù)查詢時重復(fù)計算的過程;物化視圖會在有新數(shù)據(jù)插入時進(jìn)行更新氓栈。

# 通過物化視圖提前預(yù)計算用戶下載量
CREATE MATERIALIZED VIEW download_hour_mv
ENGINE = SummingMergeTree
PARTITION BY toYYYYMM(hour) ORDER BY (userid, hour)
AS SELECT
  toStartOfHour(when) AS hour,
  userid,
  count() as downloads,
  sum(bytes) AS bytes
FROM download WHERE when >= toDateTime('2020-10-01 00:00:00')  #設(shè)置更新點渣磷,該時間點之前的數(shù)據(jù)可以通過insert into select的方式進(jìn)行插入
GROUP BY userid, hour

## 或者
CREATE MATERIALIZED VIEW db.table_MV TO db.table_new  ## table_new 可以是一張mergetree表
AS SELECT * FROM db.table_old; 

# 不建議添加populate關(guān)鍵字進(jìn)行全量更新

多表關(guān)聯(lián)

  • 當(dāng)多表聯(lián)查時,查詢的數(shù)據(jù)僅從其中一張表出時授瘦,可考慮使用IN操作而不是JOIN醋界。
select a.* from a where a.uid in (select uid from b)
# 不要寫成
select a.* from a left join b on a.uid=b.uid
  • 多表Join時要滿足小表在右的原則,右表關(guān)聯(lián)時被加載到內(nèi)存中與左表進(jìn)行比較提完。

  • clickhouse在join查詢時不會主動發(fā)起謂詞下推的操作形纺,需要每個子查詢提前完成過濾操作;需要注意的是徒欣,是否主動執(zhí)行謂詞下推逐样,對性能影響差別很大【新版本中已不再存在此問題,但是需要注意的是謂詞位置的不同依然有性能的差異】。

  • 將一些需要關(guān)聯(lián)分析的業(yè)務(wù)創(chuàng)建成字典表進(jìn)行join操作脂新,前提是字典表不易太大秽澳,因為字典表會常駐內(nèi)存。

ENGINE = Dictionary(dict_name)
或者
create database db_dic ENGINE = Dictionary

寫入和刪除優(yōu)化

  • 盡量不要執(zhí)行單條或小批量刪除和插入操作戏羽,這樣會產(chǎn)生大量小分區(qū)文件担神,給后臺merge任務(wù)帶來巨大壓力。
  • 不要一次寫入太多分區(qū)始花,或數(shù)據(jù)寫入太快妄讯,數(shù)據(jù)寫入太快會導(dǎo)致merge速度跟不上而報錯;一般建議每秒中發(fā)起2-3次寫入操作酷宵,每次操作寫入2w-5w條數(shù)據(jù)亥贸。

運(yùn)維相關(guān)

配置

配置 描述
background_pool_size 后臺用來merge進(jìn)程的大小,默認(rèn)是16浇垦,建議改成cpu個數(shù)的2倍
log_queries 默認(rèn)值為0炕置,修改為1,系統(tǒng)會自動創(chuàng)建system_query_log表男韧,并記錄每次查詢的query信息
max_execution_time 設(shè)置單次查詢的最大耗時朴摊,單位是秒;默認(rèn)無限制此虑;需要注意的是客戶端的超時設(shè)置會覆蓋該參數(shù)
max_threads 設(shè)置單個查詢所能使用的最大cpu個數(shù)甚纲;默認(rèn)是CPU核數(shù)
max_memory_usage 一般按照CPU核心數(shù)的2倍去設(shè)置最大內(nèi)存使用
max_bytes_before_external_group_by 一般按照max_memory_usage的一半設(shè)置內(nèi)存,當(dāng)group使用內(nèi)存超出閾值后會刷新到磁盤進(jìn)行

存儲

clickhouse不支持設(shè)置多數(shù)據(jù)目錄朦前,為了提升數(shù)據(jù)io性能介杆,可以掛載虛擬券組,一個券組綁定多塊物理磁盤提升讀寫性能韭寸;多數(shù)查詢場景SSD盤會比普通機(jī)械硬盤快2-3倍春哨。

數(shù)據(jù)同步

新版clickhouse提供了一個實驗性的功能,那就是我們可以將clickhouse偽裝成mysql的一個備庫去實時對齊mysql中的數(shù)據(jù)恩伺,當(dāng)mysql庫表數(shù)據(jù)發(fā)生變化時會實時同步到clickhouse中赴背;這樣就省掉了單獨(dú)維護(hù)實時spark/flink任務(wù)讀取kafka數(shù)據(jù)再存入clickhouse的環(huán)節(jié),大大降低了運(yùn)維成本提升了效率莫其。

CREATE DATABASE ckdb ENGINE = MaterializeMySQL('172.17.0.2:3306', 'ckdb', 'root', '123');

查詢?nèi)蹟?/h3>

為了避免因個別慢查詢引起的服務(wù)雪崩問題癞尚,除了可以為單個查詢設(shè)置超時以外,還可以配置周期熔斷乱陡;在一個查詢周期內(nèi)浇揩,如果用戶頻繁進(jìn)行慢查詢操作超出規(guī)定閾值后將無法繼續(xù)進(jìn)行查詢操作:


熔斷策略

綁定用戶

clickhouse權(quán)限管理與資源隔離
clickhouse高級功能上線之mysql實時數(shù)據(jù)同步

clickhouse如何構(gòu)建復(fù)雜數(shù)據(jù)模型
clickhouse sql規(guī)范

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市憨颠,隨后出現(xiàn)的幾起案子胳徽,更是在濱河造成了極大的恐慌积锅,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件养盗,死亡現(xiàn)場離奇詭異缚陷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)往核,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門箫爷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聂儒,你說我怎么就攤上這事虎锚。” “怎么了衩婚?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵窜护,是天一觀的道長。 經(jīng)常有香客問我非春,道長柱徙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任奇昙,我火速辦了婚禮护侮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘敬矩。我一直安慰自己概行,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布弧岳。 她就那樣靜靜地躺著,像睡著了一般业踏。 火紅的嫁衣襯著肌膚如雪禽炬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天勤家,我揣著相機(jī)與錄音腹尖,去河邊找鬼。 笑死伐脖,一個胖子當(dāng)著我的面吹牛热幔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讼庇,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼绎巨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蠕啄?” 一聲冷哼從身側(cè)響起场勤,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤戈锻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后和媳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體格遭,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年留瞳,在試婚紗的時候發(fā)現(xiàn)自己被綠了拒迅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡她倘,死狀恐怖璧微,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帝牡,我是刑警寧澤往毡,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站靶溜,受9級特大地震影響开瞭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罩息,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一嗤详、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓷炮,春花似錦葱色、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烘绽,卻和暖如春淋昭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背安接。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工翔忽, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盏檐。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓歇式,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胡野。 傳聞我的和親對象是個殘疾皇子材失,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345