ClickHouse 入門:MergeTree 與用 S3 做冷熱儲存
ClickHouse 入門:MergeTree 與用 S3 做冷熱儲存
ClickHouse 是一個 columnar 的 OLAP 資料庫,掃幾億列做聚合快得誇張。這篇講最低限度的上手、MergeTree 幾個有趣的地方,以及怎麼用 AWS S3 把舊資料丟到冷儲存省錢。
用 Docker 快速跑起來
最快的方式是 compose,用現成範本(clickhouse_4.8,跑 clickhouse/clickhouse-server:24.8):
git clone https://github.com/yshengliao/docker-compose-templates
cd docker-compose-templates/clickhouse_4.8
docker compose up -d
起來後有兩個介面:8123 是 HTTP、9000 是原生 TCP。連進去下 SQL:
docker exec -it clickhouse clickhouse-client
# 或走 HTTP 介面
curl 'http://localhost:8123/?query=SELECT%20version()'
範本把 clickhouse-server/ 掛成設定目錄,等一下加 S3 設定就丟這裡。
MergeTree:parts 與背景合併
MergeTree 是 ClickHouse 的主力引擎,核心行為是:每次 INSERT 不是逐列塞進一個大檔,而是產生一個獨立、依 primary key 排序好的 part;背景再用一支程序把這些 part 慢慢合併成更大的 part。名字 MergeTree 就是這麼來的,概念上接近 LSM-tree。
CREATE TABLE events
(
ts DateTime,
user_id UInt64,
event LowCardinality(String),
payload String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(ts)
ORDER BY (user_id, ts);
ORDER BY 是排序鍵,也預設兼任 primary key。MergeTree 家族還有幾個有趣的變體:ReplacingMergeTree(合併時依鍵去重)、SummingMergeTree / AggregatingMergeTree(合併時就把同鍵的數值加總 / 聚合)。把「合併」這個動作賦予語意,是 ClickHouse 很聰明的地方。
稀疏主鍵索引
ClickHouse 的 primary index 是稀疏的:它不是每列建一筆索引,而是每 index_granularity(預設 8192)列為一個 granule,只記每個 granule 的起點。好處是即使幾十億列,索引也小到能整個放進記憶體。
查詢時若條件落在 ORDER BY 的前綴上,ClickHouse 直接跳過不相干的 granule(data skipping),只讀需要的區塊。所以 ORDER BY 怎麼挑,幾乎決定了查詢快不快,把最常拿來過濾的欄位放前面。
PARTITION BY 與 TTL
PARTITION BY toYYYYMM(ts) 把資料按月切。它不是索引,而是讓你能整塊操作:查特定月份時自動 partition pruning、要刪舊資料 DROP PARTITION 一秒搞定、跨儲存層搬移也以 partition 為單位。
TTL 有兩種用法。一是讓列過期被刪:
ALTER TABLE events MODIFY TTL ts + INTERVAL 90 DAY;
二是更有趣的,時間到就把資料搬到別的儲存層,這正是冷熱分層的鉤子(下一節)。
用 S3 做冷熱暖儲存
熱資料放本機 SSD 查得快,舊資料丟 S3 省錢,ClickHouse 用 storage_configuration 把這件事做成宣告式。在 clickhouse-server/config.d/ 放一個 storage.xml(範本已經把這個目錄掛進去了):
<clickhouse>
<storage_configuration>
<disks>
<s3_cold>
<type>s3</type>
<endpoint>https://YOUR_BUCKET.s3.ap-northeast-1.amazonaws.com/clickhouse/</endpoint>
<access_key_id>YOUR_KEY</access_key_id>
<secret_access_key>YOUR_SECRET</secret_access_key>
</s3_cold>
</disks>
<policies>
<hot_cold>
<volumes>
<hot><disk>default</disk></hot> <!-- 本機 SSD -->
<cold><disk>s3_cold</disk></cold> <!-- AWS S3 -->
</volumes>
<move_factor>0.2</move_factor>
</hot_cold>
</policies>
</storage_configuration>
</clickhouse>
move_factor 是「某個 volume 剩餘空間低於這個比例(0.2 = 20%)時,自動把資料往下一層搬」。表掛上這個 policy,再用 TTL 指定多久搬到冷層:
CREATE TABLE events ( /* …同上… */ )
ENGINE = MergeTree
PARTITION BY toYYYYMM(ts)
ORDER BY (user_id, ts)
TTL ts + INTERVAL 30 DAY TO VOLUME 'cold'
SETTINGS storage_policy = 'hot_cold';
30 天內的資料留在本機 SSD(熱),之後背景自動搬到 S3(冷),查詢語法完全不變,只是冷資料慢一點。想要三層「熱 / 溫 / 冷」,就在中間多一個本機 HDD 的 volume,TTL 寫成 … + 7 DAY TO VOLUME 'warm', … + 30 DAY TO VOLUME 'cold'。
重點整理
- ClickHouse 是 columnar OLAP,MergeTree 是主力引擎:INSERT 產生排序好的 part,背景合併成大 part(概念近 LSM)。
- primary index 稀疏(每 8192 列一個 granule),索引小、可常駐記憶體;
ORDER BY的選法決定查詢能跳過多少資料。 PARTITION BY讓你以分區為單位 pruning、刪除、搬移;MergeTree 家族的 Replacing / Summing / Aggregating 把「合併」變成有語意的動作。TTL ... TO VOLUME+storage_configuration就能做冷熱分層:熱資料留 SSD、舊資料自動搬 S3,查詢語法不變。- 用 clickhouse_4.8 範本
docker compose up -d最快上手,S3 設定丟進clickhouse-server/config.d/即生效。
內文由 Claude 協助整理 · 環境 ClickHouse 24.8(LTS)+ Docker · 列入 20260613 blog 翻新計劃,新漆未乾。