强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

ClickHouse 教程 / ClickHouse 简介与架构

ClickHouse 简介与架构

1. ClickHouse 的历史

ClickHouse 最初由俄罗斯搜索引擎巨头 Yandex 开发,用于其网站流量分析工具 Yandex Metrica——全球第三大网站分析平台。

时间节点 里程碑
2009 年 Yandex Metrica 内部项目启动,名为 ClickHouse(Clickstream Data Warehouse)
2014 年 在 Yandex 内部全面替代原有 OLAP 系统
2016 年 正式开源,发布到 GitHub
2021 年 成立 ClickHouse, Inc.,获得 B 轮融资
2022 年 推出 ClickHouse Cloud(全托管云服务)
2024 年 社区持续壮大,成为最流行的开源 OLAP 数据库之一

💡 提示:ClickHouse 这个名字来源于 ClickHouse = Click(点击流)+ House(数据仓库),同时也致敬了 ClickHouse 所基于的 LSM-Tree 存储引擎思想。


2. 列式存储 vs 行式存储

ClickHouse 采用列式存储,这是其高性能的核心基础。

2.1 存储模型对比

特性 行式存储(如 MySQL) 列式存储(如 ClickHouse)
数据组织方式 按行连续存储 按列连续存储
适合场景 OLTP(增删改查) OLAP(分析查询)
读取效率 读整行快 读少量列极快
压缩效率 低(数据类型混杂) 高(同列数据类型相同)
写入效率 单行写入快 批量写入效率高
索引方式 B+Tree 稀疏索引 + 跳数索引

2.2 直观示例

假设有一张用户表:

行式存储(Row-oriented):
Row 1: [1, 'Alice', 28, 'Beijing']
Row 2: [2, 'Bob',   35, 'Shanghai']
Row 3: [3, 'Carol', 22, 'Guangzhou']

列式存储(Column-oriented):
Column 'id':      [1, 2, 3]
Column 'name':    ['Alice', 'Bob', 'Carol']
Column 'age':     [28, 35, 22]
Column 'city':    ['Beijing', 'Shanghai', 'Guangzhou']

当执行 SELECT avg(age) FROM users 时:

  • 行式存储:需要读取所有列的数据,仅使用 age
  • 列式存储:仅读取 age 列,I/O 减少约 75%

⚠️ 注意:列式存储不适合高频单行更新(UPDATE ... WHERE id = ?),这类操作在 ClickHouse 中代价很高。


3. ClickHouse 核心特性

3.1 向量化执行引擎

ClickHouse 不按行逐条处理,而是按列块(Block) 向量化处理:

-- ClickHouse 内部将数据划分为 granule(默认 8192 行)
-- 对整个 granule 进行 SIMD 向量化计算
SELECT sum(price * quantity) AS total
FROM orders
WHERE order_date >= '2026-01-01';

3.2 列式压缩

由于同列数据类型相同且数据相似度高,压缩率极高:

数据类型 典型压缩率 常用 Codec
时间序列数值 10:1 ~ 20:1 Delta + ZSTD
日志文本 5:1 ~ 10:1 LZ4
枚举/低基数 20:1 ~ 100:1 LZ4 + LowCardinality
稀疏整数 50:1 ~ 200:1 Gorilla

3.3 完整的 SQL 支持

ClickHouse 支持标准 SQL 语法,并扩展了大量分析函数:

-- 标准 SQL
SELECT
    toStartOfMonth(order_date) AS month,
    count() AS orders,
    sum(amount) AS revenue,
    uniq(user_id) AS unique_users,
    quantile(0.95)(amount) AS p95_amount
FROM orders
GROUP BY month
ORDER BY month;

3.4 其他关键特性

  • 实时数据摄入:支持秒级数据写入
  • 多副本复制:内置 ReplicatedMergeTree 引擎
  • 分片集群:支持水平分片 + 分布式查询
  • 物化视图:实时预聚合
  • 近似计算:HyperLogLog、Count-Min Sketch 等
  • 多表 JOIN:支持 ALL/ANY/ASOF JOIN

4. 架构组件

4.1 整体架构

┌──────────────────────────────────────────────────┐
│                   客户端层                         │
│   clickhouse-client / JDBC / HTTP / gRPC         │
└──────────────────┬───────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────┐
│               ClickHouse Server                   │
│  ┌──────────┐ ┌───────────┐ ┌──────────────────┐ │
│  │ TCP 服务  │ │ HTTP 服务  │ │  Inter-Server    │ │
│  │ (9000)   │ │ (8123)    │ │  通信 (9009)     │ │
│  └──────────┘ └───────────┘ └──────────────────┘ │
│  ┌──────────────────────────────────────────────┐ │
│  │           查询执行引擎(向量化)               │ │
│  └──────────────────────────────────────────────┘ │
│  ┌──────────────────────────────────────────────┐ │
│  │           表引擎(MergeTree 系列)             │ │
│  └──────────────────────────────────────────────┘ │
│  ┌──────────────────────────────────────────────┐ │
│  │           存储层(列式文件 + 索引)             │ │
│  └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
         │                         │
         ▼                         ▼
   ┌───────────┐           ┌──────────────┐
   │  本地磁盘  │           │ ZooKeeper /  │
   │ (data/)   │           │ Keeper       │
   └───────────┘           └──────────────┘

4.2 核心组件说明

组件 作用 说明
MergeTree 引擎 数据存储与合并 后台异步合并数据部分(parts)
ReplicatedMergeTree 数据复制 通过 ZooKeeper/Keeper 实现多副本同步
ZooKeeper / Keeper 分布式协调 管理副本状态、DDL 任务、选主
Distributed 表 分布式查询 路由查询到各分片,合并结果
物化视图 实时预计算 写入时触发,维护聚合结果
字典(Dictionary) 外部数据映射 关联外部数据源的键值映射

4.3 数据写入与合并流程

INSERT INTO table VALUES (...)
        │
        ▼
   写入内存 buffer
        │
        ▼ (后台线程,约每 10s)
   flush 到磁盘,形成 data part
        │
        ▼ (后台线程,异步调度)
   merge: 将多个小 part 合并为大 part
   (此过程中数据去重、TTL 过期清理等)

⚠️ 注意:ClickHouse 的 UPDATEDELETE异步操作(通过 mutation),不会立即生效,实际执行时会重写数据部分。


5. 适用场景 vs 不适用场景

5.1 适用场景 ✅

场景 说明 典型案例
OLAP 分析 大规模聚合查询 BI 报表、即席查询
日志分析 海量日志存储与检索 ELK 替代方案
实时数据分析 秒级延迟的数据看板 实时大屏
时序数据 监控指标存储与查询 Prometheus 长期存储
用户行为分析 点击流、埋点数据 漏斗、留存分析
广告归因 广告效果分析 ROI 计算

5.2 不适用场景 ❌

场景 原因 替代方案
OLTP 事务 不支持 ACID 事务 MySQL / PostgreSQL
高频单行更新 UPDATE/DELETE 代价高 MySQL / PostgreSQL
低延迟点查 稀疏索引不适合 Redis / HBase
频繁 DELETE 删除是异步 mutation MySQL / PostgreSQL
键值缓存 不适合做缓存层 Redis / Memcached
-- ❌ 不推荐:逐行更新
UPDATE users SET status = 'active' WHERE user_id = 12345;

-- ✅ 推荐:批量插入
INSERT INTO events (user_id, event_type, event_time, data)
VALUES
    (1, 'click',    now(), '{"page": "home"}'),
    (2, 'purchase', now(), '{"amount": 99.5}'),
    (3, 'click',    now(), '{"page": "search"}');

6. 与主流数据库对比

特性 ClickHouse MySQL PostgreSQL Apache Druid Apache Doris
存储模型 列式 行式 行式 列式 列式
擅长场景 OLAP OLTP OLTP/混合 OLAP(实时) OLAP
SQL 兼容性 标准 最高 较低(原生SQL)
事务支持
实时写入 高吞吐 高吞吐 高吞吐
JOIN 性能 一般 一般
运维复杂度
社区生态 活跃 最大 活跃

6.1 选型建议

-- 场景:需要实时分析 10 亿级日志数据
-- 选择:ClickHouse

-- 场景:需要事务 + 分析混合
-- 选择:PostgreSQL (OLTP) + ClickHouse (OLAP)
-- 通过 ETL 或 CDC 同步数据

-- 场景:实时指标看板,亚秒级响应
-- 选择:ClickHouse + 物化视图 预聚合

7. ClickHouse Cloud 简介

ClickHouse Cloud 是官方提供的全托管服务,适合不想自建集群的团队:

特性 说明
Serverless 架构 按需扩缩容,按实际使用计费
自动运维 无需管理 ZooKeeper、磁盘、副本
内置 S3 存储 数据持久化到对象存储
多区域部署 支持 AWS / GCP / Azure
SQL Console 内置 Web IDE
数据导入 支持 Kafka / S3 / DataLens 集成

💡 提示:对于中小团队,ClickHouse Cloud 可以大幅降低运维成本,开发阶段可用免费试用额度。


8. 第一个 ClickHouse 查询

安装 ClickHouse 后(详见下一章),尝试以下查询:

-- 创建本地表
CREATE TABLE IF NOT EXISTS hits_local
(
    WatchID UInt64,
    UserID UInt64,
    EventTime DateTime,
    URL String,
    Title String,
    Referer String
)
ENGINE = MergeTree()
ORDER BY (EventTime, UserID);

-- 插入测试数据
INSERT INTO hits_local VALUES
    (1001, 1, '2026-05-10 08:00:00', '/home',       'Homepage',    ''),
    (1002, 2, '2026-05-10 08:05:00', '/product/1',  'Product A',   '/home'),
    (1003, 1, '2026-05-10 08:10:00', '/cart',       'Cart',        '/product/1'),
    (1004, 3, '2026-05-10 09:00:00', '/home',       'Homepage',    ''),
    (1005, 2, '2026-05-10 09:15:00', '/checkout',   'Checkout',    '/cart');

-- 查询:每小时 UV 和 PV
SELECT
    toStartOfHour(EventTime) AS hour,
    count() AS page_views,
    uniq(UserID) AS unique_visitors
FROM hits_local
GROUP BY hour
ORDER BY hour;

预期输出:

┌────────────────hour─┬─page_views─┬─unique_visitors─┐
│ 2026-05-10 08:00:00 │          3 │               2 │
│ 2026-05-10 09:00:00 │          2 │               2 │
└─────────────────────┴────────────┴─────────────────┘

扩展阅读

  1. ClickHouse 官方文档
  2. ClickHouse GitHub
  3. Yandex Metrica 架构演进
  4. ClickHouse vs Druid vs Doris 对比
  5. ClickHouse Cloud 官网