ClickHouse
→ 返回 列式数据库
ClickHouse 是俄罗斯 Yandex 开源的列式分析数据库,专为 OLAP(联机分析处理) 场景设计,擅长对海量数据做实时聚合查询,单机每秒可处理数十亿行。
列式存储 vs 行式存储
| 维度 | 行式(MySQL / PostgreSQL) | 列式(ClickHouse) |
|---|---|---|
| 存储方式 | 一行数据连续存储 | 同一列数据连续存储 |
| 查询少量列 | 需读取整行,I/O 浪费 | 只读需要的列,I/O 极小 |
| 压缩比 | 低(行内数据类型混杂) | 高(同列数据类型相同,重复度高) |
| 写入方式 | 单行写入效率高 | 批量写入效率高,单行写入代价大 |
| 适用场景 | OLTP(事务处理) | OLAP(分析查询) |
核心特性
- 向量化执行引擎:CPU 指令级并行,批量处理数据块而非逐行处理
- 数据压缩:LZ4 / ZSTD 压缩,列存储压缩比通常达 10:1
- 分布式查询:数据分片到多节点,查询自动并行执行
- 近似计算:
uniqHLL12、quantileTDigest等近似函数,牺牲少量精度换极速 - 物化视图:自动维护聚合结果,查询直接命中预计算数据
表引擎
ClickHouse 的表引擎决定数据存储和查询行为,生产环境最常用 MergeTree 家族。
MergeTree(核心引擎)
CREATE TABLE events (
event_date Date,
user_id UInt64,
action String,
amount Float64,
created_at DateTime
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date) -- 按月分区
ORDER BY (event_date, user_id) -- 排序键,同时是稀疏索引
PRIMARY KEY (event_date, user_id) -- 可省略,默认等于 ORDER BY
SETTINGS index_granularity = 8192; -- 每 8192 行一个索引点ReplacingMergeTree(去重)
后台异步合并时去除重复数据,适合幂等写入场景(最终一致,不保证实时去重):
CREATE TABLE user_profiles (
user_id UInt64,
name String,
updated_at DateTime
)
ENGINE = ReplacingMergeTree(updated_at) -- 保留 updated_at 最大的版本
ORDER BY user_id;SummingMergeTree(自动求和)
合并时自动对数值列求和,适合计数/累加场景:
CREATE TABLE page_views (
site_id UInt32,
page String,
date Date,
views UInt64
)
ENGINE = SummingMergeTree(views)
ORDER BY (site_id, page, date);AggregatingMergeTree(预聚合)
配合物化视图存储聚合中间状态,查询用 -Merge 函数合并:
CREATE MATERIALIZED VIEW uv_mv
ENGINE = AggregatingMergeTree()
ORDER BY (date, page)
AS SELECT
date,
page,
uniqState(user_id) AS uv_state
FROM events
GROUP BY date, page;
-- 查询时合并中间状态
SELECT date, page, uniqMerge(uv_state) AS uv
FROM uv_mv
GROUP BY date, page;ReplicatedMergeTree(高可用)
结合 ZooKeeper 实现多副本同步:
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events', '{replica}')
ORDER BY (event_date, user_id);数据类型
| 类型 | 说明 |
|---|---|
UInt8/16/32/64 | 无符号整数 |
Int8/16/32/64 | 有符号整数 |
Float32/64 | 浮点数 |
Decimal(P, S) | 精确小数,金融场景用 |
String | 变长字符串 |
Date / DateTime | 日期 / 时间 |
Array(T) | 数组,如 Array(String) |
Nullable(T) | 可为 NULL,尽量避免(影响性能) |
LowCardinality(T) | 低基数优化,枚举类字段推荐 |
LowCardinality(String)比String在低基数字段(性别、状态、地区)上查询快数倍。
索引机制
ClickHouse 的主键是稀疏索引,不同于 MySQL 的 B+ 树:
- 每隔
index_granularity(默认 8192)行存一个索引点 - 查询时定位到对应的数据块(granule),再扫描块内数据
- 主键不保证唯一性,仅用于加速范围查询
跳数索引(Skip Index):
CREATE TABLE events (
event_date Date,
user_id UInt64,
city String,
INDEX idx_city city TYPE bloom_filter GRANULARITY 4
)
ENGINE = MergeTree()
ORDER BY (event_date, user_id);常用查询
聚合分析
SELECT
toDate(created_at) AS date,
count() AS pv,
uniq(user_id) AS uv,
sum(amount) AS revenue
FROM events
WHERE created_at >= '2024-01-01'
AND created_at < '2024-02-01'
GROUP BY date
ORDER BY date;漏斗分析
SELECT level, count() AS users
FROM (
SELECT
user_id,
windowFunnel(86400)(
created_at,
action = 'register',
action = 'view_product',
action = 'add_cart',
action = 'order'
) AS level
FROM events
WHERE event_date >= '2024-01-01'
GROUP BY user_id
)
GROUP BY level
ORDER BY level;Array 函数
-- 展开数组行(类似 UNNEST)
SELECT user_id, tag
FROM users
ARRAY JOIN tags AS tag;
-- 聚合为数组
SELECT user_id, groupArray(action) AS action_sequence
FROM events
GROUP BY user_id;写入最佳实践
ClickHouse 不适合高频单行写入,频繁小批量写入会导致 Too many parts 错误。
| 做法 | 说明 |
|---|---|
| 批量写入 | 每批至少 1000 行,推荐 10w+ 行 |
| Buffer 引擎 | 内存缓冲后批量刷入主表 |
| 消息队列 | Kafka → ClickHouse,削峰填谷 |
| 避免频繁 UPDATE/DELETE | 用 ReplacingMergeTree 替代 |
-- Buffer 引擎示例
CREATE TABLE events_buffer AS events
ENGINE = Buffer(
currentDatabase(), events,
16, -- 分片数
10, 100, -- 刷新时间:最短 10s,最长 100s
10000, 1000000, -- 刷新行数区间
10000000, 1000000000 -- 刷新字节数区间
);分布式部署
-- 分布式表:查询路由到各 shard,结果合并返回
CREATE TABLE events_distributed AS events
ENGINE = Distributed(
cluster_name,
currentDatabase(),
events, -- 本地表名
rand() -- 分片键
);常见模式:写本地表,查分布式表
- 写入时直连各节点写本地表,避免分布式写入的双倍网络开销
- 查询时查分布式表,自动跨节点聚合
与 MySQL 数据同步
生产中常见架构:MySQL(OLTP)→ ClickHouse(OLAP)
-- ClickHouse 直读 MySQL 外部表
CREATE TABLE mysql_orders
ENGINE = MySQL('mysql-host:3306', 'mydb', 'orders', 'user', 'password');
-- 定期同步增量数据
INSERT INTO orders_local
SELECT * FROM mysql_orders
WHERE updated_at >= yesterday();或通过 CDC 工具(Canal、Debezium)消费 MySQL binlog 实时同步至 ClickHouse。
Spring Boot 集成
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.6.0</version>
</dependency>spring:
datasource:
url: jdbc:clickhouse://localhost:8123/mydb
username: default
password: ""
driver-class-name: com.clickhouse.jdbc.ClickHouseDriver相关集成:
适用场景
| 场景 | 推荐 |
|---|---|
| 用户行为分析、埋点统计 | ClickHouse ✅ |
| 实时大屏、监控看板 | ClickHouse ✅ |
| 日志存储与分析 | ClickHouse ✅ |
| 业务订单、用户数据(OLTP) | MySQL / PostgreSQL |
| 全文搜索 | Elasticsearch |
| 向量相似度搜索 | Milvus |
相关
- MySQL — OLTP 场景,与 ClickHouse 互补
- PostgreSQL — 兼顾分析的关系型数据库
- Elasticsearch — 日志分析的另一选择
- Redis — 缓存层,减轻查询压力