在 ClickHouse 中,表格設計並不是隨便定義欄位就好,因為不同的欄位屬性、型別選擇、壓縮策略,會直接影響 儲存空間 與 查詢效能。
今天我們就來深入探討實戰中最容易忽略的幾個細節,包括:
在 ClickHouse 中,Nullable(T)
會額外為每列儲存一個 null bitmap(每列 1 bit),即使大多數值不是 NULL,也會有空間消耗。
如果欄位幾乎不會是 NULL,改用 DEFAULT
會更省空間。
設定方式 | 儲存空間 | 查詢效能 | 適用情境 |
---|---|---|---|
Nullable | 多 1 bit/列 | 無明顯差異 | 資料缺失頻繁 |
Default | 無額外 bitmap | 無明顯差異 | 欄位幾乎都有值 |
建議:
-- 不推薦
age Nullable(UInt8)
-- 推薦
age UInt8 DEFAULT 0
ClickHouse 的 columnar 儲存讓我們可以用更小的型別節省大量空間。
整數範圍選擇:
UInt8
→ 0~255UInt16
→ 0~65535UInt32
→ 一般 IDUInt64
→ 需支援非常大的整數 ID浮點與 Decimal:
Decimal(9, 2)
Float64
日期與時間:
Date
(2 bytes)DateTime
(4 bytes)對於重複率高的字串(如地區、狀態),LowCardinality(String)
會使用字典映射,大幅減少重複儲存。
ALTER TABLE orders
MODIFY COLUMN status LowCardinality(String);
欄位類型 | 重複率高時空間使用 | 重複率低時空間使用 |
---|---|---|
String | 高 | 高 |
LowCardinality(String) | 低 | 反而略高 |
適用固定長度欄位(如代碼、哈希值),壓縮效率高,但不足長度會補零,可能浪費空間。
code FixedString(8)
ClickHouse 可針對欄位設定壓縮方式,例如:
ZSTD
:高壓縮比DoubleDelta
:適合時間序列數字Delta
:適合日期欄位CREATE TABLE events
(
id UInt32 CODEC(ZSTD(3)),
date Date CODEC(DoubleDelta)
) ENGINE = MergeTree();
CREATE TABLE user_events
(
EventDate Date DEFAULT today(),
UserID UInt32,
Action LowCardinality(String),
Version UInt8 DEFAULT 1
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(EventDate)
ORDER BY (EventDate, UserID);
EventDate
用 Default,省掉 Nullable bitmapAction
用 LowCardinality 減少字串重複儲存Version
用 UInt8 並設定 Default表格設計是 ClickHouse 成本優化與效能的第一步。
透過合理選擇欄位屬性(Default、型別、LowCardinality、Codecs),可以在相同硬體資源下 省下數倍空間,並讓查詢速度大幅提升。