1. ClickHouse 入门:从一次真实需求说起

先讲个我自己的经历。几年前我在一家电商公司做数据平台,每天要处理几亿条用户行为日志。MySQL 扛不住了,Hive 又太慢。老板说:「我要实时看每个商品的点击率,延迟不能超过 5 秒。」我当时心里就一句话——这玩意儿,得换个思路。

后来我找到了 ClickHouse。嗯,就是今天我们要聊的主角。

1.1 什么是 ClickHouse

ClickHouse 是一个开源的列式存储数据库,专门为 OLAP(在线分析处理)场景设计。它由俄罗斯的 Yandex 公司开发,2016 年开源。说白了,它就是用来「快速查大量数据」的。

你想想看,传统数据库查 10 亿行可能要几分钟,ClickHouse 可能只要几秒。我刚开始也不信,直到我在生产环境实测了一次——同样的查询,MySQL 跑了 47 秒,ClickHouse 只用了 0.8 秒。从那以后,我就成了它的忠实用户。

核心定位:ClickHouse 不是用来替代 MySQL 做事务处理的,它是专门做「分析型查询」的引擎。如果你需要的是 OLTP(在线事务处理),请继续用 MySQL 或 PostgreSQL。

1.2 OLAP 场景特点

要理解 ClickHouse,先得明白 OLAP 是什么。我习惯把数据处理分成两类:

特性 OLTP(在线事务处理) OLAP(在线分析处理)
典型场景 订单系统、用户登录 报表分析、用户画像
数据操作 频繁的增删改 批量导入、大量读取
查询特点 每次查几条记录 每次扫描几百万到几十亿行
响应要求 毫秒级 秒级到分钟级
数据量级 GB 级别 TB 到 PB 级别

OLAP 场景有几个典型特征:

  • 读多写少——数据一旦写入,很少修改
  • 大范围扫描——经常要查几亿行数据做聚合
  • 列式聚合——比如 SUM、COUNT、AVG 这类操作
  • 时间序列——大部分分析都跟时间有关

我曾经帮一个客户做广告投放分析,他们每天产生 5 亿条曝光日志。用传统数据库做「按小时统计各广告位的曝光量」,跑一次要 15 分钟。换成 ClickHouse 后,同样的查询只需要 2 秒。这就是 OLAP 场景下,选对工具的威力。

1.3 ClickHouse 核心特性

ClickHouse 为什么这么快?我总结了几个关键点:

1.3.1 列式存储

这是 ClickHouse 最核心的设计。后面我们会详细对比,这里先记住一句话:列式存储只读取需要的列,行式存储要读整行。

1.3.2 向量化执行

ClickHouse 不是一条一条处理数据,而是一次处理一批数据(比如 1024 行)。这充分利用了 CPU 的 SIMD 指令集。我刚开始接触这个概念时也觉得抽象,后来看了一个性能对比:同样的聚合计算,逐行处理要 100ms,向量化只需要 5ms。

1.3.3 数据压缩

列式存储天然适合压缩。同一列的数据类型相同,重复值多,压缩比可以做到 5:1 甚至 10:1。我在一个项目中,原始数据 10TB,在 ClickHouse 里只占了 1.2TB。这不仅省了存储成本,还让 I/O 更快了。

1.3.4 分布式架构

ClickHouse 支持水平扩展。你可以把数据分片到多台机器上,查询时自动并行处理。嗯,这里要注意:分布式不是 ClickHouse 的默认模式,但它是原生支持的。

个人建议:刚开始学习时,先用单机版。等理解了核心概念,再考虑分布式部署。我见过太多人一上来就搭集群,结果问题都出在配置上,反而忽略了 ClickHouse 本身的强大。

1.4 列式存储 vs 行式存储

这是理解 ClickHouse 的关键。我画了一张图,帮你直观感受两者的区别:

列式存储 vs 行式存储 行式存储(Row-Oriented) 行1: ID=1, Name=Alice, Age=25, City=Beijing 行2: ID=2, Name=Bob, Age=30, City=Shanghai 行3: ID=3, Name=Charlie, Age=28, City=Guangzhou 行4: ID=4, Name=Diana, Age=35, City=Shenzhen 查询 Age 列时,需要读取所有行 列式存储(Column-Oriented) ID列: 1, 2, 3, 4 Name列: Alice, Bob, Charlie, Diana Age列: 25, 30, 28, 35 City列: Beijing, Shanghai, Guangzhou, Shenzhen 查询 Age 列时,只读取 Age 列 行式存储:适合 OLTP,频繁增删改查单行 列式存储:适合 OLAP,大量数据聚合分析

看到区别了吗?行式存储把一整行数据挨着放,列式存储把同一列的数据挨着放。这个差异在查询时影响巨大。

举个例子:假设你有 1 亿行数据,每行有 100 个字段。你想统计所有人的平均年龄。

  • 行式存储:需要读取所有 100 个字段 × 1 亿行 = 100 亿个字段值
  • 列式存储:只需要读取年龄这一列 = 1 亿个字段值

差了 100 倍的 I/O 量。这就是 ClickHouse 快的根本原因之一。

避坑提醒:我曾经遇到一个团队,把 ClickHouse 当 MySQL 用,频繁做单行更新。结果性能惨不忍睹。记住:ClickHouse 不适合频繁的 UPDATE/DELETE 操作。它的设计哲学是「一次写入,多次读取」。

1.5 什么时候该用 ClickHouse

根据我的经验,以下场景非常适合 ClickHouse:

  • 用户行为分析(点击流、页面浏览)
  • 监控和日志分析(服务器指标、错误日志)
  • 实时报表(按秒/分钟聚合的看板)
  • AB 测试结果分析
  • 广告投放效果统计

以下场景不适合:

  • 需要事务支持(银行转账)
  • 频繁的单行更新(用户资料修改)
  • 复杂的 JOIN 查询(超过 3 个表的大表 JOIN)
  • 数据量很小(几千行,MySQL 完全够用)

我的经验:如果你不确定某个场景是否适合 ClickHouse,先问自己一个问题——「这个查询需要扫描多少行?」如果答案是「几百万行以上」,那 ClickHouse 大概率是正确答案。