ClickHouse命令行與SQL語法詳解
- 一、ClickHouse命令行與SQL語法詳解
- 第一部分:ClickHouse SQL 命令行客戶端 (`clickhouse-client`)
- 1. 基礎連接
- 2. 核心命令行參數
- 3. 數據導入與導出實戰
- 第二部分:ClickHouse SQL 語法詳解
- 1. DDL (數據定義語言)
- 2. DML (數據操作語言)
- 3. 查看元數據
- 第三部分:實戰示例與最佳實踐
- 示例 1:用戶行為分析
- 示例 2:使用 `FINAL` 優化版本合并
- 最佳實踐:
- 二、常見高級用法
- 1. 物化視圖 (Materialized Views) - 預聚合之王
- 2. 高級聚合函數與聚合狀態
- a. 近似計算 (Approximate Calculations)
- b. 聚合狀態管理 (`*State` / `*Merge`)
- 3. 窗口函數 (Window Functions)
- 4. 高性能連接 (JOIN) 策略
- a. 使用字典 (Dictionaries) 代替小表 JOIN
- b. 正確的 JOIN 語法和順序
- 5. 嵌套數據結構與 Map 類型
- a. 使用 `Nested` 類型模擬嵌套結構
- b. 使用 `Map` 類型 (推薦)
- 6. 外部數據與表函數 (Table Functions)
- 7. 數據生命周期管理 (TTL)
- 8. 項目投影 (Projections)
- 總結與最佳實踐
- 三、數據類型
- 一、基礎類型
- 1. 整數類型(固定長度,有符號/無符號)
- 2. 浮點類型(近似計算)
- 3. 十進制類型(精確計算)
- 4. 布爾類型
- 二、字符串類型
- 1. `String`
- 2. `FixedString(N)`
- 三、時間日期類型
- 四、復雜與高階類型
- 1. `Array(T)`
- 2. `Nullable(T)`
- 3. `Tuple(T1, T2, ...)`
- 4. `LowCardinality(T)`
- 5. `Enum8`, `Enum16`
- 五、域類型(Domain-Specific Types)
- 1. `IPv4`, `IPv6`
- 2. `UUID`
- 六、其他特殊類型
- 1. `Nested`
- 2. `AggregateFunction`
- 總結與最佳實踐
- 四、相關文獻
一、ClickHouse命令行與SQL語法詳解
第一部分:ClickHouse SQL 命令行客戶端 (clickhouse-client
)
clickhouse-client
是與 ClickHouse 服務器交互的主要命令行工具。
1. 基礎連接
連接本地默認實例:
clickhouse-client
指定連接參數:
clickhouse-client \--host=your-clickhouse-server.com \ # 或 -h--port=9000 \ # 或 -P--user=default \ # 或 -u--password \ # 安全方式,會提示輸入密碼--database=my_database # 或 -d,指定初始數據庫
2. 核心命令行參數
參數 | 說明 | 示例 |
---|---|---|
-q, --query | 執行單條查詢后退出 | -q "SELECT 1" |
-m, --multiline | 允許多行查詢(按回車不立即執行) | clickhouse-client -m |
--multiquery | 允許 -q 參數中包含多條用分號分隔的 SQL | -q "SELECT 1; SELECT 2;" |
-f, --format | 極其重要:指定輸入/輸出格式 | --format=CSV |
--time | 打印查詢執行時間 | --time |
-i, --input_format | 指定輸入數據的格式(用于 INSERT ) | --input_format=CSV |
--vertical | 以垂直格式輸出結果(適用于寬表) | --vertical |
--param_<name> | 為參數化查詢傳參 | --param_id=5 (配合 {id:UInt32} ) |
3. 數據導入與導出實戰
導出查詢結果到 CSV 文件:
clickhouse-client -q "SELECT *FROM salesWHERE event_date = today()
" --format=CSVWithNames > sales_today.csv
從 CSV 文件導入數據:
# 假設 data.csv 格式: 1,Alice,100.5
clickhouse-client -q "INSERT INTO my_tableFORMAT CSV
" < data.csv# 或者使用管道
cat data.csv | clickhouse-client -q "INSERT INTO my_table FORMAT CSV"
常用格式: JSONEachRow
, CSV
, TSV
, PrettyCompact
(默認,人類可讀), Null
(不輸出,用于測試性能)。
第二部分:ClickHouse SQL 語法詳解
ClickHouse 的 SQL 語法與標準 SQL 高度兼容,但包含大量針對分析場景的擴展和優化。
1. DDL (數據定義語言)
a. 創建數據庫
CREATE DATABASE IF NOT EXISTS my_db
ENGINE = Atomic; -- 默認引擎,推薦
b. 創建表(核心)
ClickHouse 的強大功能很大程度上體現在其豐富的表引擎上。
MergeTree 系列 (最核心):
CREATE TABLE my_table (event_date Date, -- 日期event_time DateTime, -- 時間user_id UInt32, -- 用戶ID,無符號32位整型page_url String, -- 字符串duration Float32, -- 浮點數status Enum8('success' = 1, 'fail' = 2) -- 枚舉
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date) -- 按年月分區
ORDER BY (event_date, user_id) -- 排序鍵(主鍵)
SETTINGS index_granularity = 8192; -- 索引粒度
PARTITION BY
:分區鍵。通常按日期分區,加速數據管理和刪除。ORDER BY
:排序鍵(ClickHouse 的主鍵概念)。這是查詢性能最關鍵的因素,決定了數據在磁盤上的存儲順序。PRIMARY KEY
:主鍵(與ORDER BY
默認相同),用于一級索引。
其他常用引擎:
Log
/TinyLog
/StripeLog
:用于小表或臨時數據。Memory
:內存表,重啟后數據丟失。Kafka
:用于從 Kafka 主題消費數據。MySQL
/PostgreSQL
:將外部數據庫的表映射到 ClickHouse。MaterializedView
:物化視圖,自動轉換和聚合數據。Distributed
:分布式表引擎,不存儲數據,而是將查詢路由到集群中的分片上。
c. 修改表
-- 添加列
ALTER TABLE my_table ADD COLUMN browser String AFTER user_id;-- 修改列類型
ALTER TABLE my_table MODIFY COLUMN duration UInt32;-- 刪除列
ALTER TABLE my_table DROP COLUMN browser;
2. DML (數據操作語言)
a. 插入數據 (INSERT
)
-- 標準插入
INSERT INTO my_table VALUES (..., ...);-- 指定列插入
INSERT INTO my_table (event_date, user_id) VALUES ('2023-10-01', 12345);-- 從查詢結果插入
INSERT INTO target_table
SELECT ... FROM source_table WHERE ...;
b. 查詢數據 (SELECT
) - 核心中的核心
ClickHouse 的 SELECT
支持所有標準語法,并有許多強大擴展。
嵌套子查詢和 CTE:
WITH active_users AS (SELECT DISTINCT user_idFROM eventsWHERE event_date >= today() - 7
)
SELECTu.user_id,count() AS event_count
FROM active_users AS u
JOIN events AS e ON u.user_id = e.user_id
GROUP BY u.user_id
HAVING event_count > 10;
數組操作 (特色功能):
SELECTuser_id,-- 創建數組['pageview', 'login', 'purchase'] AS actions,-- 數組函數:計算長度length(actions) AS action_count,-- 數組函數:判斷是否存在has(actions, 'login') AS has_login,-- 數組函數:聚合組內數據成數組groupArray(page_url) AS visited_pages
FROM events
GROUP BY user_id;
高級函數:
SELECT-- 條件函數if(duration > 10, 'Long', 'Short') AS session_type,-- 多條件分支multiIf(status = 200, 'OK', status = 404, 'Not Found', 'Error') AS status_desc,-- 聚合函數:近似去重(極快)uniqHLL12(user_id) AS approx_unique_users,-- 聚合函數:分位數quantile(0.99)(duration) AS p99_duration
FROM events
GROUP BY session_type, status_desc;
c. 刪除數據 (ALTER TABLE ... DELETE
)
注意:ClickHouse 的 DELETE
是異步的、后臺執行的 ALTER
操作。
ALTER TABLE my_table DELETE WHERE event_date < '2023-01-01';
3. 查看元數據
-- 查看所有數據庫
SHOW DATABASES;-- 查看表結構
DESCRIBE TABLE my_table;-- 查看建表語句
SHOW CREATE TABLE my_table;-- 查看表大小和行數
SELECTname,formatReadableSize(total_bytes) AS size,total_rows
FROM system.parts
WHERE table = 'my_table' AND active;
第三部分:實戰示例與最佳實踐
示例 1:用戶行為分析
-- 計算每小時的PV和UV,以及平均會話時長
SELECTtoStartOfHour(event_time) AS hour,count() AS pv, -- 頁面瀏覽量uniq(user_id) AS uv, -- 獨立用戶數avg(duration) AS avg_duration
FROM events
WHERE event_date = today()
GROUP BY hour
ORDER BY hour;
示例 2:使用 FINAL
優化版本合并
對于 CollapsingMergeTree
或 ReplacingMergeTree
引擎,查詢時使用 FINAL
可以強制合并版本,但可能很慢。
SELECT *
FROM my_replacing_table
FINAL
WHERE user_id = 123;
最佳實踐:
- 避免
SELECT *
:始終指定需要的列。列式存儲下,讀取不需要的列代價高昂。 - 優先使用分區鍵和排序鍵:在
WHERE
和ORDER BY
子句中優先使用這些列,以利用索引。 - 使用近似計算:如
uniqHLL12()
代替uniqExact()
,用quantile()
代替精確分位數,以極大提升性能。 - 預聚合:使用
SummingMergeTree
或AggregatingMergeTree
引擎和物化視圖,在數據寫入時進行預聚合。 - 謹慎使用
JOIN
:ClickHouse 的JOIN
性能不如傳統 OLTP 數據庫。通常建議反規范化(寬表)或預先過濾右表。 - 關注數據類型:使用最緊湊、最合適的數據類型(如
UInt32
而非UInt64
)。
通過熟練掌握 clickhouse-client
工具和 ClickHouse 特有的 SQL 語法,你可以極大地提升大數據分析的效率和性能。
二、常見高級用法
下文將深入探討 ClickHouse 數據分析的高級用法,包括物化視圖、高級聚合、近似計算、分布式查詢優化等核心特性。
1. 物化視圖 (Materialized Views) - 預聚合之王
物化視圖是 ClickHouse 中最強大的功能之一。它不是一個簡單的視圖,而是一個在底層隱式創建并持續更新的特殊表。當源表 (INSERT
) 寫入新數據時,物化視圖會自動、增量地將這些數據按照預定義的聚合邏輯進行計算和存儲。
場景:實時計算每分鐘的頁面瀏覽量(PV)和獨立用戶數(UV)。
基礎表 (存儲原始數據):
CREATE TABLE events_raw (event_time DateTime,user_id UInt32,page_url String,event_type String
) ENGINE = MergeTree()
ORDER BY (event_time, user_id);
物化視圖 (存儲預聚合結果):
CREATE MATERIALIZED VIEW events_agg_minute
ENGINE = SummingMergeTree() -- 指定物化視圖自身的存儲引擎
PARTITION BY toYYYYMM(event_minute)
ORDER BY (event_minute, page_url)
AS SELECTtoStartOfMinute(event_time) AS event_minute,page_url,count() AS pv, -- 求和合并uniqState(user_id) AS uv_state -- 存儲UV的中間狀態(AggregateFunction類型)
FROM events_raw
GROUP BY event_minute, page_url;
查詢物化視圖:
SELECTevent_minute,page_url,sum(pv) AS pv, -- 對pv直接求和uniqMerge(uv_state) AS uv -- 對UV狀態進行合并計算
FROM events_agg_minute
GROUP BY event_minute, page_url;
優勢:
- 查詢極快:直接查詢預先計算好的聚合結果,而非掃描原始數據。
- 開銷極低:在數據插入時增量計算,分散了計算壓力。
2. 高級聚合函數與聚合狀態
ClickHouse 提供了豐富的聚合函數,特別是對于中間狀態 (*State
) 和合并結果 (*Merge
) 的操作,這是實現預聚合的基礎。
a. 近似計算 (Approximate Calculations)
以精度換取速度,非常適合海量數據下的快速分析。
-
基數估計:
-- 精確去重 (慢) SELECT uniqExact(user_id) FROM events;-- 近似去重 (極快,誤差~1.5%) SELECT uniq(user_id) FROM events; SELECT uniqHLL12(user_id) FROM events; -- 更老的算法
-
分位數估計:
-- 計算響應時間的中位數、90分位、99分位 SELECTquantile(0.5)(response_time_ms) AS p50,quantile(0.9)(response_time_ms) AS p90,quantile(0.99)(response_time_ms) AS p99 FROM requests;
b. 聚合狀態管理 (*State
/ *Merge
)
這是實現物化視圖和高級聚合的基石。
-- 1. 查詢時直接使用狀態函數,返回二進制狀態,不是最終值。
SELECT quantileState(0.5)(response_time_ms) AS p50_state FROM requests;-- 2. 將狀態存入表或物化視圖(如上文的uv_state)。
-- 3. 在更高層的聚合中,合并這些狀態得到最終結果。
SELECT quantileMerge(0.5)(p50_state) AS final_p50 FROM agg_table;
3. 窗口函數 (Window Functions)
ClickHouse 支持標準的 SQL 窗口函數,用于復雜的數據分析。
場景:計算每個用戶最近3次訪問的頁面時長移動平均。
SELECTuser_id,event_time,page_url,duration_ms,avg(duration_ms) OVER (PARTITION BY user_idORDER BY event_time ASCROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 最近3行(當前行 + 前2行)) AS moving_avg_duration
FROM events
ORDER BY user_id, event_time;
常用窗口函數:row_number()
, rank()
, lag()
, lead()
, sum() OVER (...)
, avg() OVER (...)
。
4. 高性能連接 (JOIN) 策略
在 OLAP 數據庫中,JOIN
是昂貴的操作。ClickHouse 提供了多種策略來優化。
a. 使用字典 (Dictionaries) 代替小表 JOIN
將小維度表預加載到內存中。
-- 1. 創建字典
CREATE DICTIONARY products_dict (id UInt64,name String,price Decimal(10, 2)
) PRIMARY KEY id
SOURCE(CLICKHOUSE(TABLE 'products' DB 'default'))
LIFETIME(MIN 300 MAX 360)
LAYOUT(HASHED());-- 2. 使用dictGet函數代替JOIN
SELECTorder_id,dictGet('default.products_dict', 'name', product_id) AS product_name,dictGet('default.products_dict', 'price', product_id) AS product_price,quantity * product_price AS total_amount
FROM orders;
b. 正確的 JOIN 語法和順序
- 將小表放在右側:ClickHouse 總是將右表加載到內存中。
- 使用
GLOBAL JOIN
:在分布式查詢中,確保右表被發送到所有節點。SELECT ... FROM distributed_left_table AS l GLOBAL INNER JOIN local_small_right_table AS r ON l.id = r.id;
5. 嵌套數據結構與 Map 類型
處理半結構化數據,如 JSON 中的數組或鍵值對。
a. 使用 Nested
類型模擬嵌套結構
CREATE TABLE events (timestamp DateTime,user_id UInt32,`tags.keys` Array(String),`tags.values` Array(String)
) ENGINE = MergeTree()
ORDER BY (user_id, timestamp);-- 查詢:查找包含標簽 "env":"prod" 的事件
SELECT *
FROM events
WHERE has((tags.keys, tags.values), ('env', 'prod'));
b. 使用 Map
類型 (推薦)
CREATE TABLE events (timestamp DateTime,user_id UInt32,tags Map(String, String)
) ENGINE = MergeTree()
ORDER BY (user_id, timestamp);-- 查詢更加直觀
SELECT *
FROM events
WHERE tags['env'] = 'prod';
6. 外部數據與表函數 (Table Functions)
無需建表,直接查詢外部數據源。
-
查詢 CSV 文件:
SELECT * FROM file('data.csv', CSVWithNames, 'column1 String, column2 UInt32') WHERE column2 > 100;
-
查詢 URL:
SELECT * FROM url('https://example.com/data.json', JSONEachRow, 'id UInt32, data String');
-
查詢 MySQL 表:
SELECT * FROM mysql('mysql-host:3306', 'database', 'table', 'user', 'password');
7. 數據生命周期管理 (TTL)
自動處理舊數據,是實現數據分區和保留策略的核心。
-
行級 TTL:自動刪除或移動過期數據。
CREATE TABLE logs (event_time DateTime,message String ) ENGINE = MergeTree() ORDER BY event_time TTL event_time + INTERVAL 30 DAY; -- 30天后自動刪除數據-- 或者將數據移動到廉價存儲 TTL event_time + INTERVAL 7 DAY TO DISK 'hdd2',event_time + INTERVAL 30 DAY TO VOLUME 'archive';
-
列級 TTL:自動將某列重置為默認值。
CREATE TABLE sessions (created DateTime,session_data String TTL created + INTERVAL 1 HOUR ) ENGINE = MergeTree() ORDER BY created;
8. 項目投影 (Projections)
物化視圖的現代替代品,與主表數據一起存儲,由查詢優化器自動選擇使用,無需應用層干預。管理更簡單,性能更高。
場景:為不同的排序鍵創建投影以加速不同維度的查詢。
CREATE TABLE sales (event_date Date,product_id UInt32,customer_id UInt32,amount Decimal(10, 2)
) ENGINE = MergeTree()
ORDER BY (event_date, product_id); -- 主排序鍵-- 創建一個按客戶ID聚合的投影
ALTER TABLE salesADD PROJECTION sales_by_customer (SELECTevent_date,customer_id,sum(amount)GROUP BY event_date, customer_id);-- 插入數據后,投影會自動構建
INSERT INTO sales ...;-- 查詢時,ClickHouse 優化器會自動判斷是否使用投影
SELECT event_date, customer_id, sum(amount)
FROM sales
GROUP BY event_date, customer_id; -- 此查詢會命中投影,極快!
總結與最佳實踐
高級用法 | 核心思想 | 適用場景 |
---|---|---|
物化視圖 (Materialized Views) | 空間換時間,預聚合 | 實時報表、指標看板 |
近似計算 (uniq, quantile) | 精度換速度 | 海量數據下的快速趨勢分析 |
聚合狀態 (State/Merge) | 分布式聚合 | 構建分層聚合系統 |
字典 (Dictionaries) | 內存換時間,避免JOIN | 關聯小維度表 |
窗口函數 (Window Functions) | 行間計算 | 用戶行為分析、時間序列分析 |
Map類型 / 投影 | 處理半結構化數據 | 處理JSON、標簽等靈活字段 |
TTL | 自動化數據管理 | 日志、事件等有時效性的數據 |
表函數 (file, url, mysql) | 聯邦查詢 | 數據探查、臨時分析、數據集成 |
項目投影 (Projections) | 自動查詢優化 | 為不同維度的查詢加速 |
終極建議:
- 優先考慮預聚合:90% 的性能問題可以通過物化視圖和投影解決。
- 敢于使用近似計算:在可接受的誤差范圍內,換取數量級的性能提升。
- 避免大表 JOIN:使用字典、反規范化(寬表)或應用程序層處理。
- 擁抱 TTL:讓數據管理自動化,避免手動清理的麻煩和風險。
- 嘗試投影:在新的設計中,優先使用投影而不是物化視圖來加速查詢。
掌握這些高級用法,你就能充分利用 ClickHouse 的潛力,構建出高效、穩定且易于維護的海量數據分析平臺。
三、數據類型
一、基礎類型
1. 整數類型(固定長度,有符號/無符號)
設計哲學:提供多種長度的整數,讓你可以精確選擇所需位數,避免浪費空間。
類型 | 取值范圍(有符號) | 取值范圍(無符號) | 存儲字節 | 示例 |
---|---|---|---|---|
Int8 | -128 到 127 | - | 1 | Int8(5) |
Int16 | -32768 到 32767 | - | 2 | Int16(1000) |
Int32 | -2^31 到 2^31-1 | - | 4 | Int32(42500) |
Int64 | -2^63 到 2^63-1 | - | 8 | Int64(34200000000) |
UInt8 | - | 0 到 255 | 1 | UInt8(255) (狀態碼) |
UInt16 | - | 0 到 65535 | 2 | UInt16(60000) |
UInt32 | - | 0 到 2^32-1 | 4 | UInt32(4000000000) |
UInt64 | - | 0 到 2^64-1 | 8 | UInt64(100000000000) |
最佳實踐:永遠使用能滿足你數據范圍的最小類型。例如,存儲年齡用 UInt8
,存儲頁面訪問量用 UInt32
。
2. 浮點類型(近似計算)
設計哲學:犧牲微小精度以換取極高的計算速度,適合大規模數值計算。
類型 | 精度 | 存儲字節 | 備注 |
---|---|---|---|
Float32 | 約 7 位有效數字 | 4 | 單精度,對應 float |
Float64 | 約 16 位有效數字 | 8 | 雙精度,對應 double |
注意:由于浮點數的精度問題,對它們進行相等比較 (=
) 可能是不可靠的。適用于指標計算、科學計算,不適用于金融金額。
3. 十進制類型(精確計算)
設計哲學:提供精確的定點數運算,適合金融、貨幣等需要精確計算的場景。
類型 | 語法 | 說明 | 示例 |
---|---|---|---|
Decimal32 | Decimal32(S) | 精度最高為 9 位數字,S 為小數位數 | Decimal32(4) -> 總共9位,小數占4位 |
Decimal64 | Decimal64(S) | 精度最高為 18 位數字 | Decimal64(8) |
Decimal128 | Decimal128(S) | 精度最高為 38 位數字 | Decimal128(16) |
Decimal256 | Decimal256(S) | 精度最高為 76 位數字 | Decimal256(30) |
最佳實踐:根據所需的整數位數和小數位數來選擇。例如,存儲全球GDP可能需要 Decimal128(2)
。
4. 布爾類型
ClickHouse 沒有單獨的 Boolean
類型。它使用 UInt8
類型,用 0
和 1
來表示 false
和 true
。
二、字符串類型
1. String
- 說明:可以存儲任意長度的文本,長度無限制。編碼為 UTF-8。
- 適用場景:默認的字符串類型。存儲URL、日志、JSON字符串、變長文本等。
- 示例:
'Hello, 世界!'
,'https://example.com'
2. FixedString(N)
- 說明:固定長度
N
的字符串。如果插入的字符串長度小于N
,則會用空字節 (\0
) 填充;如果更長,則會拋出異常。 - 適用場景:存儲長度幾乎固定的標識符,如 MD5哈希值(32)、國家代碼(2)、IP地址(15) 等。查詢性能比
String
更高。 - 示例:
FixedString(32)
用于存儲'4d7e6e7b0d6e7a7b6e7d6e7a6e7d6e7a'
三、時間日期類型
設計哲學:提供細粒度的時間類型,內部存儲為整數,計算效率極高。
類型 | 分辨率 | 格式 | 示例 |
---|---|---|---|
Date | 天 | YYYY-MM-DD | '2023-10-27' |
DateTime | 秒 | YYYY-MM-DD HH:MM:SS | '2023-10-27 14:30:00' |
DateTime64 | 亞秒 | YYYY-MM-DD HH:MM:SS.NNNNNNNNN | DateTime64(3) -> 毫秒 '2023-10-27 14:30:00.123' |
關鍵點:
- 可以指定時區:
DateTime('Asia/Shanghai')
。 DateTime64
可以指定小數秒的精度,如DateTime64(6)
為微秒。- 最佳實踐:始終使用最細粒度的時間類型,因為你總是可以從高精度轉換到低精度(如按天聚合),但反之則不行。
四、復雜與高階類型
這些類型是 ClickHouse 強大功能的體現。
1. Array(T)
- 說明:由
T
類型元素組成的數組,T
可以是任意類型,甚至另一個Array
。 - 操作:支持豐富的數組函數 (
arrayMap
,arrayFilter
,arrayCount
) 和 Lambda 表達式。 - 示例:
-- 創建數組 SELECT [1, 2, 3] AS numbers; -- 數組函數 SELECT arrayFilter(x -> x > 1, [1, 2, 3, 4]) AS filtered; -- [2,3,4]
2. Nullable(T)
- 說明:允許
T
類型的值為NULL
。 - 注意:謹慎使用!
Nullable
類型會使列的處理速度變慢并增加存儲開銷,因為需要額外的一個字節來存儲NULL
標記。如果業務上不可能為NULL
,就不要用。 - 示例:
Nullable(String)
表示一個可能為NULL
的字符串。
3. Tuple(T1, T2, ...)
- 說明:元組,用于存儲一組有序的、類型可能不同的值。
- 適用場景:臨時組合多個值,常用于函數返回多個結果或存儲少量關聯數據。
- 示例:
Tuple(String, UInt8, Float32)
->('Alice', 25, 99.5)
4. LowCardinality(T)
- 說明:極其重要的高性能類型。用于包裝基數低( distinct 值數量少)的
String
、FixedString
、Date
、DateTime
類型以及整數類型。 - 原理:內部使用字典編碼,將原始值映射為更小的整數,極大減少存儲空間并加速查詢。
- 適用場景:狀態碼、性別、國家、枚舉值、標簽等。
- 示例:
LowCardinality(String)
存儲'success'
,'fail'
,'pending'
。
5. Enum8
, Enum16
- 說明:枚舉,將字符串映射到數字值進行存儲,是
LowCardinality
的一種特化和提前定義。 - 適用場景:固定的、預定義的字符串集合。
- 示例:
CREATE TABLE logs (level Enum8('ERROR' = 1, 'WARNING' = 2, 'INFO' = 3) ); INSERT INTO logs VALUES ('ERROR');
五、域類型(Domain-Specific Types)
這些類型是語法糖,底層用其他類型存儲,但提供了更清晰的語義和專用的函數。
1. IPv4
, IPv6
- 底層存儲:
IPv4
存為UInt32
,IPv6
存為FixedString(16)
。 - 優點:提供專用的函數(如
IPv4NumToString
,toIPv4
)和格式檢查。 - 示例:
SELECT toIPv4('192.168.0.1') AS ip WHERE ip > toIPv4('192.168.0.0');
2. UUID
- 說明:通用唯一標識符,存儲為
FixedString(16)
。 - 示例:
UUID('12345678-1234-1234-1234-123456789abc')
六、其他特殊類型
1. Nested
- 說明:用于創建嵌套數據結構,它本質上是將多個
Array
列組合在一起,保證其數組長度相同。 - 適用場景:處理半結構化數據,如來自 JSON 的事件列表。
- 示例:
(注意:這實際上是模擬嵌套,并非真正的嵌套類型,但概念一致)。CREATE TABLE events (timestamp DateTime,user_id UInt32,`actions.names` Array(String),`actions.values` Array(Int32) ) ENGINE = MergeTree() ORDER BY (user_id, timestamp);
2. AggregateFunction
- 說明:非常特殊且強大。它不存儲數據本身,而是存儲數據的中間聚合狀態(如
uniqState
,quantileState
)。 - 適用場景:與物化視圖結合使用,實現預聚合,是 ClickHouse 應對超大數據量的王牌功能。
- 示例:
-- 創建一個存儲聚合狀態的物化視圖 CREATE MATERIALIZED VIEW mv_agg ENGINE = AggregatingMergeTree() ORDER BY (date, product_id) AS SELECTdate,product_id,sumState(amount) AS total_amount, -- 存儲的是聚合狀態,不是最終值uniqState(user_id) AS unique_users FROM sales_raw GROUP BY date, product_id;-- 查詢時,使用相應的合并函數獲取最終結果 SELECTdate,product_id,sumMerge(total_amount) AS total_sales, -- 合并狀態得到最終結果uniqMerge(unique_users) AS total_customers FROM mv_agg GROUP BY date, product_id;
總結與最佳實踐
- 精確選擇類型:使用能滿足需求的最小、最精確的類型(如
UInt8
而非UInt64
)。 - 字符串優化:對基數低的字符串列,毫不猶豫地使用
LowCardinality(String)
。對固定長度的標識符,使用FixedString(N)
。 - 避免濫用 Nullable:除非必要,否則不要使用
Nullable
,因為它有性能開銷。 - 時間類型:始終使用最細粒度的時間類型(如
DateTime64
)。 - 金融計算:使用
Decimal
系列類型,避免使用Float
。 - 探索復雜類型:善用
Array
、Tuple
和Map
來處理復雜數據結構。 - 王牌功能:在需要極致性能的聚合場景,學習和使用
AggregateFunction
與物化視圖。
通過合理選擇數據類型,你可以極大地提升 ClickHouse 的存儲效率和查詢性能。
四、相關文獻
【大數據知識】ClickHouse入門
【大數據知識】今天聊聊Clickhouse部署方案