背景
小編最近在做一個數(shù)據(jù)類產(chǎn)品項目,每天涉及到幾十億數(shù)據(jù)的匯總計算,從不同維度、不同的關(guān)聯(lián)關(guān)系進行匯總統(tǒng)計,剛開始時項目組使用的是hive,寫好大量的業(yè)務(wù)SQL計算邏輯后(中間有一些其他程序處理腳本),每天通過定時任務(wù)來生成數(shù)據(jù),然后把生成的數(shù)據(jù)推送到研發(fā)端的ES(Elasticsearch),研發(fā)端基于ES查詢數(shù)據(jù),給到前端來展示
但是,隨著項目的不斷深入,產(chǎn)品需求的快速迭代,之前的各種統(tǒng)計指標更新迭代,基于hive數(shù)據(jù)庫的計算方式不能再滿足當(dāng)前快速迭代的場景。項目組經(jīng)過調(diào)研,最終選擇Clickhouse數(shù)據(jù)庫,讓研發(fā)來每天通過查詢Clickhouse數(shù)據(jù)庫,來統(tǒng)計生成各種統(tǒng)計指標,并把結(jié)果緩存至ES
項目數(shù)據(jù)架構(gòu)的大概思路:
- hive每日生成明細數(shù)據(jù),把這些明細數(shù)據(jù)導(dǎo)入Clickhouse
- 在Clickhouse中生成一些中間表,供研發(fā)人員查詢數(shù)據(jù)使用,方便進行各種拼接組合
- 研發(fā)人員每日基于明細表、中間表,計算統(tǒng)計指標,把結(jié)果緩存至ES
小編環(huán)境
操作系統(tǒng)版本 與 Clickhouse 版本
cat /etc/redhat-release
# CentOS Linux release 7.2.1511 (Core)
clickhouse -V
#ClickHouse local version 24.7.2.13 (official build)
登錄客戶端
clickhouse-client -u xxxx --password xxxxxx -m
-u 或者 --user :指定用戶名
--password :密碼
-m 或者 --multiline :進入客戶端后,運行輸入多行sql語句
建表
在Clickhouse中,數(shù)據(jù)既可以存放到單個服務(wù)器節(jié)點,也可以把數(shù)據(jù)分散存放到集群中各個節(jié)點服務(wù)器中,這個需要看數(shù)據(jù)量大小,來選擇合適的表類型
-
創(chuàng)建本地表
如果數(shù)據(jù)量比較小的話,建議選擇本地表,在數(shù)據(jù)查詢時以提高性能,可以節(jié)省節(jié)點之間數(shù)據(jù)傳輸?shù)臅r間,比如有幾千萬行數(shù)據(jù)的表,完全可以選擇本地表,但是查詢數(shù)據(jù)時,只能在當(dāng)前服務(wù)器節(jié)點查詢,其他服務(wù)器節(jié)點沒有該表
下面以用戶表為列,進行建表操作:
create table test.user_table (
uid String comment '用戶id',
sex String comment '性別',
age UInt16 comment '年齡',
phone String comment '聯(lián)系電話'
)
engine = MergeTree()
order by uid;
- 數(shù)據(jù)類型需要注意是大寫開頭 ,
String
、UInt16
,表引擎類型也必須大寫MergeTree
- 如果沒有指定主鍵的話,默認用 order by 指定的字段
-
創(chuàng)建分布式表
分布式表在Clickhouse中,只是一個視圖,不實際存放數(shù)據(jù),指向?qū)嶋H存放數(shù)據(jù)的本地表,所以在創(chuàng)建分布式表時,需要在各個服務(wù)器節(jié)點創(chuàng)建名字一模一樣的本地表
--在集群中創(chuàng)建實際存放數(shù)據(jù)的本地表
create table test.user_event on cluster data_cluster(
uid String comment '用戶id',
event String comment '事件名稱',
c_time DateTime comment '點擊時間',
dt Date comment '日期'
)
engine = MergeTree()
partition by dt
order by uid;
--創(chuàng)建分布式表
create table test.user_event_distributed (
uid String comment '用戶id',
event String comment '事件名稱',
c_time DateTime comment '點擊時間',
dt Date comment '日期'
)
engine = Distributed('data_cluster', 'test', 'user_event', rand())
;
分布式表需要選擇 Distributed
表引擎,其中
第1個參數(shù):集群名稱
第2個參數(shù):數(shù)據(jù)庫名
第3個參數(shù):數(shù)據(jù)表名
第3個參數(shù):分片key,數(shù)據(jù)被到不同服務(wù)器依據(jù)的字段,相同的值會被分配到同一臺服務(wù)器
如果在創(chuàng)建分布式表 test.user_event_distributed
時沒有指定 on cluster data_cluster
,那么創(chuàng)建是本地表,后續(xù)的查詢只能在建表的那個節(jié)點服務(wù)器查詢數(shù)據(jù),這里小編就創(chuàng)建的是一個本地表
查詢
Clickhouse 的sql 查詢語句和hive的比較類似,使用起來基本沒啥差距,只有極個別的函數(shù)不支持,下面小編列舉一下自己在使用時,遇到的個別函數(shù):
- 沒有
nvl
函數(shù),需要用coalesce
代替 - 支持窗口函數(shù),
row_number
等 - 沒有
concat_ws
,需要用arrayStringConcat
代替 - 沒有
collect_list
,需要用groupArray
代替 - 一個好用的函數(shù),
arrayZip
,類似python中的zip - 沒有
split
函數(shù),需要用splitByString
代替 -
arrayMap
、arraySum
、arraySlice
等函數(shù)很好用,性能高
表變更
- 刪除特定分區(qū)
alter table test.user_event on cluster data_cluster drop partition '2024-11-30';
alter table test.user_event on cluster data_cluster delete where dt > '2024-11-15';
alter table test.user_event on cluster data_cluster delete where dt='2024-11-30';
- 刪除滿足特定條件數(shù)據(jù)
alter table test.user_event on cluster data_cluster delete where user_id='u00001';
自定義函數(shù)
不推薦使用外部語言編寫自定義函數(shù),例如:java、python 等,推薦使用自有的函數(shù),逐步組合實現(xiàn)自定義函數(shù),性能高
一個樣例:
--分割字符串并把類型轉(zhuǎn)換為整數(shù)
create function x_split as (x) ->
(
arrayMap(
y -> toUInt32(y),
splitByString(',', x)
)
);
歷史相關(guān)文章
- Clickhouse中創(chuàng)建生成日期序列自定義函數(shù)
- Python 基于pyhive庫操作hive
- Rust 是否會重寫 Python 解釋器與有關(guān)的庫,替代 C 語言地位?
- Python中的Lambda匿名函數(shù)
以上是自己實踐中遇到的一些問題,分享出來供大家參考學(xué)習(xí),歡迎關(guān)注微信公眾號:DataShare ,不定期分享干貨