
ClickHouse 是什么:特点与一步步安装(2026 指南)
发布于:
阅读时间: 5 min
主题: 技术
作者: Leandro Valencia
给独立开发者的 ClickHouse 实践指南:它是什么、为什么这么快、关键特性,以及如何用 curl 或 Docker 在 5 分钟内装好。
目录
ClickHouse 是什么(不讲营销话术)
ClickHouse 是一个开源的列式分析数据库,用 C++ 写成,设计目的是以"看起来像测量误差"的速度对大数据量做聚合查询。
关键词是分析。在数据库行话里,这指的是 OLAP(联机分析处理),与 PostgreSQL 或 MySQL 做的 OLTP(联机事务处理)相对。
这个区别比看起来重要:
OLTP(Postgres、MySQL、SQLite) 被优化来非常快地读写单行。"给我用户 4821"。"更新这个订单的状态"。每秒数千次小操作,带事务和强一致性。
OLAP(ClickHouse、DuckDB、BigQuery) 被优化来读很多行但很少列。"给我过去 90 天按国家汇总的收入"。它不在乎某具体一行,它在乎的是扫掉数百万行并压成一个数。
如果你想看这个类别的完整背景——历史、用例和厂商地图——我在 OLAP 数据库是什么 里展开讲过。
让它成为可能的技术关键是列式存储。一个按行的数据库在磁盘上这样存数据:
[id:1, país:ES, ingresos:42, timestamp:...][id:2, país:MX, ingresos:17, timestamp:...]
你要累加 ingresos 列,就得把所有东西都读出来,包括你并不关心的 país 和 timestamp。ClickHouse 把每一列存到自己的文件里:
ingresos: [42, 17, 88, 12, ...]
país: [ES, MX, ES, AR, ...]
要累加 ingresos,你只读这个文件。如果你的表有 40 列,而你的查询用 2 列,你只读了 5% 的数据。魔法就是从这开始的,剩下的一切都在放大它。
为什么这么快:四个真正的原因
1. 残酷的压缩。 当你把同类型的值放在一起、而且还排好序,模式就会重复,压缩算法变得非常高效。ClickHouse 文档给出的压缩比,从自由文本的 2x 一路到排好序的低基数列的 1,000x 以上。磁盘上字节更少 = I/O 更少 = 查询更快。
2. 稀疏主索引。 ClickHouse 不为每行建一条 B 树索引。它建的是稀疏索引:每 8,192 行(一个"颗粒")一条。这意味着每 TB 数据只要几 MB 索引,轻松装进内存。代价是 ClickHouse 永远不查精确的一行,而是查它所在的块。对分析来说,这是完全正确的取舍。
3. 向量化 + 并行引擎。 操作不是逐行执行,而是用 SIMD 指令在列的块上执行。而且会激进地并行到所有可用核心。在 8 核笔记本上你就感觉得到差别;在 64 核服务器上是另一个级别。
4. 读写分离。 插入会创建新的"part",在后台合并(LSM 风格的架构)。插入不阻塞查询,查询也不阻塞插入。
你应该知道的主要特性
这些才是真正会改变你项目设计的东西,而不是 datasheet 上的完整清单。
单个二进制、零依赖
这听起来像个小细节,但对小项目来说很可能是最重要的一点。ClickHouse 以单个可执行文件分发,内含服务器、客户端和本地模式。没有 JVM、没有强制的 ZooKeeper、没有编排器。你下载一个文件,运行它,你就有一个分析数据库。
把它和启动 Apache Druid 对比一下——Druid 需要六种不同的进程。对单打独斗的独立开发者来说,这个差别决定了项目是上线还是死在 docker-compose.yml 里。
clickhouse-local:对文件跑 SQL、不用起服务器
你可以直接从磁盘或 URL 查 CSV、Parquet 或 JSON,不用导入任何东西,也不用起服务器:
./clickhouse local --query "
SELECT country, count() AS visitas
FROM file('logs.csv', CSVWithNames)
GROUP BY country
ORDER BY visitas DESC
LIMIT 10
"
这能替代用 pandas 写的快速探索脚本,在大文件上明显更快。
增量物质化视图
这是最改变我构建方式的一个特性。ClickHouse 的物质化视图不是会刷新的缓存:它是一个插入触发器。每次你往源表插入,这个块上的聚合就被算出来、写到目标表里。
结果是:你把成本从查询时刻挪到了插入时刻。你的 dashboard 查的是一张 4,000 行的预聚合表,而不是 4 亿行的原始数据。我在进阶指南里深入讲,但先把这个概念记住。
完整 SQL 支持加上真 JOIN
多年来对 ClickHouse 的标准批评是"JOIN 差"。现在已经站不住脚了。它支持所有标准 JOIN 类型,有一个用列统计来重排 JOIN 的优化器,还加了标准 SQL 里没有的类型,比如 ASOF JOIN(按最接近的时间点而不是精确值来连接),这对时序和金融数据是纯金。
它还用数百个分析函数扩展 SQL:uniqExact、quantileTDigest、windowFunnel、sequenceMatch。在 Postgres 里要写 60 行 CTE 的东西,在这里是一个函数。
兼容 70+ 种格式和数据湖
它能读写 Parquet、Iceberg、Delta Lake、Avro、Protobuf、各种 JSON。它能直接查 S3 上的文件而不摄入。这意味着它不会把你锁住:哪天你想迁移,一条语句数据就以 Parquet 出来了。
不爆 schema 的 JSON
你可以用原生 JSON 类型摄入半结构化数据,它内部以列式存储。不用提前设计完美 schema 就能摄入形状各异的事件,而仍然保有列式数据库的性能。
我的看法:什么时候 ClickHouse 是对的选择、什么时候不是
这是大多数教程会让你失望的地方,因为它们是想卖你东西的人写的。
ClickHouse 是好主意,如果:
你有一张停不下来地增长的事件表——产品分析、日志、指标、点击、IoT 遥测——而你的查询是对时间范围做聚合。这是经典用例,也是它会像魔法的地方。
你在做面向用户的分析:你产品里的一个 dashboard,很多客户同时查。ClickHouse 以毫秒级延迟处理高并发,而这正是 Snowflake 这类数仓变贵的地方。
你的 BigQuery 或 Snowflake 账单让你焦虑。一台每月 30-60 欧的 ClickHouse 专用服务器,能扛下在按消费计费的数仓上贵一个数量级的负载。对 bootstrap 的项目来说这不是优化,是可行和不可行的差别。
ClickHouse 是坏主意,如果:
你需要频繁按行更新和删除。ClickHouse 在这方面进步很大(轻量 mutation、ReplacingMergeTree、轻量删除),但它仍然是一个为"写一次、读多次"设计的引擎。如果你的负载是 CRUD,用 Postgres。
你需要多表 ACID 事务。事务支持有限,而且不是项目目标。别把订单状态放在这里。
你的数据少于几百万行。50 万行的表,Postgres 加一个像样的索引就能毫秒级回答。加 ClickHouse 是没有收益的运维复杂度。小数据集的正确答案是不换数据库。
你的团队是 0 个人,而你已经要维护三个服务。这是又一个要监控、备份、升级的服务。只有性能痛点是真实的时候才值得,而不是预期中的时候。
我的实操规则:如果在你最大的表上跑一个 GROUP BY 在 Postgres 里要超过 5 秒,而这条查询是你产品的核心,就是时候看 ClickHouse 了。 在此之前,不要。
还有一点补充:对我最有效的模式不是替换 Postgres,而是把两者放在一起。Postgres 继续做事务的真相来源——用户、订单、配置——而 ClickHouse 通过 CDC 或复制任务接收事件表的副本。各自做各自擅长的事。
ClickHouse 一步步安装
来点实操。根据你的需要,有三条路。
方式 1:用 curl 快速安装(macOS、Linux、FreeBSD)
最直接的办法。下载适合你系统的二进制:
curl https://clickhouse.com/ | sh
在 Linux 和 macOS 上,这还会把 clickhousectl(别名 chctl)装到 ~/.local/bin,这是用来管理多个本地版本、在后台启动服务器、与 ClickHouse Cloud 连接的官方 CLI。
如果你只想要二进制、不要管理 CLI:
curl https://clickhouse.com/ | CLICKHOUSE_ONLY=1 sh
给 macOS 用户的提示: 如果 Gatekeeper 抱怨无法验证二进制的开发者,到"系统设置 → 隐私与安全性"里批准运行。这是 macOS 对未签名二进制的正常行为。
启动服务器:
./clickhouse server
在另一个终端里启动客户端:
./clickhouse client
你应该会看到类似这样的输出:
ClickHouse client version 24.5.1.117 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 24.5.1.
local-host :)
数据存在当前目录,服务器重启后还在。
方式 2:Docker(如果你已经在用容器,推荐)
当项目已经有 docker-compose.yml 时,这是我的默认选择,因为它不弄脏系统、环境可复现。
docker run -d \
--name clickhouse \
-p 8123:8123 \
-p 9000:9000 \
-v clickhouse_data:/var/lib/clickhouse \
--ulimit nofile=262144:262144 \
clickhouse/clickhouse-server
这两个端口很重要,一开始每个人都搞混:
- 8123 是 HTTP 接口。大多数 Web 客户端、BI 工具和
curl用它。 - 9000 是原生 TCP 协议。更快更紧凑;
clickhouse-client和原生驱动用它。
--ulimit nofile 这个参数实际上不可省:ClickHouse 会打开很多文件描述符,不提高上限的话负载下会出莫名其妙的错误。
写成 docker-compose.yml:
services:
clickhouse:
image: clickhouse/clickhouse-server
container_name: clickhouse
ports:
- "8123:8123"
- "9000:9000"
volumes:
- clickhouse_data:/var/lib/clickhouse
- ./config.d:/etc/clickhouse-server/config.d
ulimits:
nofile:
soft: 262144
hard: 262144
environment:
CLICKHOUSE_USER: creacosas
CLICKHOUSE_PASSWORD: cambia_esto
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
volumes:
clickhouse_data:
连到容器里的客户端:
docker exec -it clickhouse clickhouse-client --user creacosas --password cambia_esto
方式 3:什么都不装
如果你只想试一下语法、感受速度,官方 playground 里有已加载的真实数据集,并能在浏览器里执行查询。零摩擦。
你的第一批查询:从零到真实数据
我们来做点接近真实场景的东西:一个网站的事件表。
建库建表
CREATE DATABASE creacosas;
USE creacosas;
CREATE TABLE eventos
(
fecha Date,
timestamp DateTime,
usuario_id UInt32,
evento LowCardinality(String),
pais LowCardinality(String),
url String,
duracion_ms UInt32
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(fecha)
ORDER BY (evento, fecha, usuario_id);
这里有三处值得展开的决策,因为它们是ClickHouse 式的决策:
ENGINE = MergeTree 是默认表引擎,90% 的情况你都用它。整个 MergeTree 家族(ReplacingMergeTree、SummingMergeTree、AggregatingMergeTree)共享同一个底座,在 part 合并上加了额外行为。
ORDER BY 是你整个 schema 里最重要的决策。它定义了数据在磁盘上的物理顺序,默认也是主键。规则:把你最常用来过滤、且基数更低的列放前面。我们几乎总是按事件类型和日期过滤,所以它们在前。这里搞错,是"ClickHouse 慢"的头号原因。
LowCardinality(String) 是一个会做字典编码的类型。如果一列的不同值少于约 10,000 个(国家、事件类型、套餐名),把它包进 LowCardinality 会减少存储并明显加速过滤。这是一个几乎没人一开始会用的免费收益。
插入测试数据
我们来生成 1000 万行合成数据,好有东西玩:
INSERT INTO eventos
SELECT
toDate('2026-01-01') + (number % 220) AS fecha,
toDateTime(fecha) + (number % 86400) AS timestamp,
(number % 50000) + 1 AS usuario_id,
['pageview','click','signup','purchase'][(intHash32(number) % 4) + 1] AS evento,
['ES','MX','AR','CO','CL','US'][(intHash32(number + 7) % 6) + 1] AS pais,
concat('/pagina/', toString(number % 500)) AS url,
(number % 5000) + 100 AS duracion_ms
FROM numbers(10000000);
numbers() 函数即时生成行:这是 ClickHouse 里不下载任何东西就能造测试数据集的标准办法。我对类别列不用 number % N 而用 intHash32(),是因为如果两列都用以有公因子的模数(比如 4 和 6),它们会相关,结果会人为地均匀。
查询
SELECT
pais,
evento,
count() AS total,
round(avg(duracion_ms)) AS duracion_media,
uniqExact(usuario_id) AS usuarios_unicos
FROM eventos
WHERE fecha >= '2026-03-01'
AND evento = 'purchase'
GROUP BY pais, evento
ORDER BY total DESC;
注意客户端输出的最后一行。它告诉你处理了多少行、读了多少字节、速度是多少:
6 rows in set. Elapsed: 0.021 sec. Processed 1.14 million rows, 8.32 MB (54.28 million rows/s., 396.19 MB/s.)
那个数字——总共 1000 万行里的"processed 1.14 million rows"——才是关键。ClickHouse 只读了表的 11%,因为 ORDER BY (evento, fecha, ...) 让它跳过了其他所有东西。优化 ClickHouse 几乎总是围绕降低这个数字。
一个小技巧:看磁盘上的实际大小
SELECT
table,
formatReadableSize(sum(data_compressed_bytes)) AS comprimido,
formatReadableSize(sum(data_uncompressed_bytes)) AS sin_comprimir,
round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 2) AS ratio
FROM system.columns
WHERE database = 'creacosas'
GROUP BY table;
系统表(system.columns、system.parts、system.query_log)是 ClickHouse 最赞的东西之一:引擎的全部内省都是可查询的 SQL。
你会犯的错(我都犯过)
一行一行地插入。 ClickHouse 讨厌小插入。每次 INSERT 都在磁盘上创建一个新"part",之后还要合并。一千次单行插入会产生一千个 part,服务器会因 Too many parts 报错而窒息。每次至少 1,000 行批量插入——理想是 10,000 到 100,000——或者开启 async_insert=1 异步插入。
习惯性地用 Nullable。 每个 Nullable 列都会多加一列掩码、并禁用一些优化。如果你能用哨兵值(0、空字符串、1970-01-01),就用。
把高基数列放在 ORDER BY 第一位。 如果你把 usuario_id 或 UUID 放前面,你就破坏了压缩和跳块能力。低基数在前,永远如此。
期望 UPDATE 像 Postgres 那样工作。 能用,但操作很重。如果你的设计依赖不断更新行,请重新考虑设计(或重新考虑数据库)。
结论
ClickHouse 不是通用数据库,而这正是它的价值:它把一件事——对大体量做聚合——做得比几乎所有人都好,而且以相对于其能力而言小得离谱的运维占用做到。一个二进制、零依赖,从笔记本到数百节点用同一个引擎跑。
对单打独斗的独立开发者来说,最后这一点才是决定性的。你不需要一个数据团队来运维 VPS 上的 ClickHouse。你需要的是好好理解 ORDER BY,以及不要逐行插入。
如果你是从 Postgres 过来的、dashboard 奄奄一息,那就给它一个下午。初始学习曲线是几个小时而不是几周,而性能跃升是那种不用测量都能感觉到的。
在本系列的下一批文章里,我们深入装好之后的两个问题:
- ClickHouse 的替代方案:完整对比 —— DuckDB、StarRocks、Druid、Pinot、TimescaleDB 和云数仓,带对比表和按用例的结论。
- ClickHouse 进阶指南 —— 物质化视图、projection、压缩编码、TTL、S3 分层和慢查询诊断。
常见问题
ClickHouse 免费吗?
引擎是 Apache 2.0 开源的,你可以无成本、无功能限制地自托管。ClickHouse Cloud 是付费的托管服务,采用计算与存储分离、按消费计费的模型,无活动时可以缩到零。
ClickHouse 能替代 PostgreSQL 吗?
一般情况下不能。它们是干不同活的工具:Postgres 做事务和应用状态,ClickHouse 做分析。常见模式是两个都用,Postgres 当真相来源,ClickHouse 接收事件数据。
多大数据量才值得?
作为实操参考,事件表从几千万行开始,差别就很明显了。少于几百万行的话,索引良好的 Postgres 就够了,运维也更简单。
在 Windows 上能跑吗?
可以,通过 Docker 或 WSL2,这是推荐路径。也可以通过 clickhousectl 安装。
该用什么表引擎?
90% 的情况用 MergeTree。需要按键去重就用 ReplacingMergeTree,作为聚合物质化视图的目标就用 SummingMergeTree 或 AggregatingMergeTree。
相关文章
继续探索您可能感兴趣的相似内容

ClickHouse 进阶指南:优化、物质化视图和真实技巧
如何把 ClickHouse 发挥到极致:ORDER BY、物质化视图、projection、编码、TTL、S3 分层和慢查询诊断。带真实 SQL。

OLAP 数据库:是什么、真实用例和主要厂商
OLAP 数据库是什么、与 OLTP 有何不同、带真实 SQL 的实用案例,以及 2026 年的主要厂商。

2026 年 ClickHouse 的替代方案:带表格的诚实对比
DuckDB、StarRocks、Druid、Pinot、TimescaleDB、BigQuery 等。对 ClickHouse 替代方案的真实比较,带表格和按用例的推荐。