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

clickhouse在易企秀數據倉庫項目中已投入使用兩年,主要為內部用戶提供快速查詢和多維分析的能力;希望你在業務當中遇到的性能問題,在這里都能得到解決

Clickhouse堪稱OLAP領域的黑馬,最近發布的幾個版本在多表關聯分析上也有了極大的性能提升,尤其是還引入了MaterializeMySQL Database Engine做到了實時對齊業務線mysql中的數據。

表優化

數據類型

  • 建表時能用數值型或日期時間型表示的字段,就不要用字符串——全String類型在以Hive為中心的數倉建設中常見,但CK環境不應受此影響。

  • 雖然clickhouse底層將DateTime存儲為時間戳Long類型,但不建議直接存儲Long類型,因為DateTime不需要經過函數轉換處理,執行效率高、可讀性好。

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

  • 數值類型分組最快,在新版本中ck會對string類型進行一次hash映射再分組

分區和索引

  • 分區粒度根據業務特點決定,不宜過粗或過細。一般選擇按天分區,也可指定為tuple();以單表1億數據為例,分區大小控制在10-30個為最佳。
PARTITION BY tuple() 
  • 必須指定索引列,clickhouse中的索引列即排序列,通過order by指定,一般在查詢條件中經常被用來充當篩選條件的屬性被納入進來;可以是單一維度,也可以是組合維度的索引;通常需要滿足高基列在前、查詢頻率大的在前原則;還有基數特別大的不適合做索引列,如用戶表的userid字段;通常篩選后的數據滿足在百萬以內為最佳。

表參數

  • index_granularity 是用來控制索引粒度的 默認是8192,如非必須不建議調整。

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

查詢優化

單表查詢

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

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

采樣修飾符只有在mergetree engine表中才有效,且在創建表時需要指定采樣策略;

  • 數據量太大時應避免使用select * 操作,查詢的性能會與查詢的字段大小和數量成線性變換;字段越少,消耗的io資源就越少,性能就會越高。

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

  • 如非必須不要在結果集上構建虛擬列,虛擬列非常消耗資源浪費性能,可以考慮在前端進行處理,或者在表中構造實際字段進行額外存儲。
select id ,pv, uv , pv/uv rate 
  • 使用 uniqCombined 替代 distinct 性能可提升10倍以上,uniqCombined 底層采用類似HyperLogLog算法實現,如能接收2%左右的數據誤差,可直接使用這種去重方式提升查詢性能。

  • 對于一些確定的數據模型,可將統計指標通過物化視圖的方式進行構建,這樣可避免數據查詢時重復計算的過程;物化視圖會在有新數據插入時進行更新。

# 通過物化視圖提前預計算用戶下載量
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')  #設置更新點,該時間點之前的數據可以通過insert into select的方式進行插入
GROUP BY userid, hour

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

# 不建議添加populate關鍵字進行全量更新

多表關聯

  • 當多表聯查時,查詢的數據僅從其中一張表出時,可考慮使用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時要滿足小表在右的原則,右表關聯時被加載到內存中與左表進行比較。

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

  • 將一些需要關聯分析的業務創建成字典表進行join操作,前提是字典表不易太大,因為字典表會常駐內存。

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

寫入和刪除優化

  • 盡量不要執行單條或小批量刪除和插入操作,這樣會產生大量小分區文件,給后臺merge任務帶來巨大壓力。
  • 不要一次寫入太多分區,或數據寫入太快,數據寫入太快會導致merge速度跟不上而報錯;一般建議每秒中發起2-3次寫入操作,每次操作寫入2w-5w條數據。

運維相關

配置

配置 描述
background_pool_size 后臺用來merge進程的大小,默認是16,建議改成cpu個數的2倍
log_queries 默認值為0,修改為1,系統會自動創建system_query_log表,并記錄每次查詢的query信息
max_execution_time 設置單次查詢的最大耗時,單位是秒;默認無限制;需要注意的是客戶端的超時設置會覆蓋該參數
max_threads 設置單個查詢所能使用的最大cpu個數;默認是CPU核數
max_memory_usage 一般按照CPU核心數的2倍去設置最大內存使用
max_bytes_before_external_group_by 一般按照max_memory_usage的一半設置內存,當group使用內存超出閾值后會刷新到磁盤進行

存儲

clickhouse不支持設置多數據目錄,為了提升數據io性能,可以掛載虛擬券組,一個券組綁定多塊物理磁盤提升讀寫性能;多數查詢場景SSD盤會比普通機械硬盤快2-3倍。

數據同步

新版clickhouse提供了一個實驗性的功能,那就是我們可以將clickhouse偽裝成mysql的一個備庫去實時對齊mysql中的數據,當mysql庫表數據發生變化時會實時同步到clickhouse中;這樣就省掉了單獨維護實時spark/flink任務讀取kafka數據再存入clickhouse的環節,大大降低了運維成本提升了效率。

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

查詢熔斷

為了避免因個別慢查詢引起的服務雪崩問題,除了可以為單個查詢設置超時以外,還可以配置周期熔斷;在一個查詢周期內,如果用戶頻繁進行慢查詢操作超出規定閾值后將無法繼續進行查詢操作:


熔斷策略

綁定用戶

clickhouse權限管理與資源隔離
clickhouse高級功能上線之mysql實時數據同步

clickhouse如何構建復雜數據模型
clickhouse sql規范

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380