第 1 章 ClickHouse 定位与能力全景
章节定位:这是《ClickHouse 从理论到实践》的开篇。后面 19 章会深入到建表、查询、写入、集成、调优、运维各个细节,但那些细节只有在你先搞清楚"ClickHouse 到底是什么、它擅长什么、它不擅长什么"之后才有意义。所以第 1 章不写复杂的 SQL,只做三件事:把 ClickHouse 的出身和设计取向讲清楚,把它的架构一眼看全,把它的能力边界和生态位画出来。
本系列限定的核心技术组合是Kafka、MySQL、Flink、Paimon、Doris——也就是围绕 ClickHouse 最常出现的五个上下游系统。这一章我们会先把这五者和 ClickHouse 的分工关系铺开,后面第 10~14 章再逐个动手打通。
学习目标
读完本章,你应该能够:
- ✓ 说清 ClickHouse 的出身与演进,理解它"为分析而生"的设计取向
- ✓ 用三层架构(查询处理层 / 存储层 / 集成层)判断任意一项功能属于哪一层
- ✓ 区分 ClickHouse 的五种部署形态与四种接入协议,知道什么场景该选哪一种
- ✓ 拿出一份"适用 / 反场景"清单,对业务需求做第一轮快速判断
- ✓ 说清 ClickHouse 与 Kafka、MySQL、Flink、Paimon、Doris 各自的生态分工
- ✓ 在零安装环境下亲手跑通第一条 ClickHouse 查询,并看到列存与后台合并的效果
1.1 它为什么值得你花时间
先给结论:ClickHouse 是一个把"扫描 + 聚合"这件事做到接近硬件极限的列式 OLAP 数据库。如果你的场景是"在几十亿甚至上万亿行、几百列的表上,用大量并发查询、要求亚秒级返回",那它基本是目前市面上最快的选项之一。这句话不是营销腔,是它自己的技术定位——ClickHouse 团队在 2024 年的 VLDB 论文摘要里就是这么写的:面向 PB 级数据集、高写入速率、高并发、期望实时延迟的分析型场景。
1.1.1 出身:从 Yandex 的日志分析器长出来
理解一个数据库的性格,最好从它最初被造出来解决什么问题开始。
- 2009 年,ClickHouse 在 Yandex 内部诞生,最初只是网页分析(Web Analytics)里用来做过滤和聚合的算子——要处理的是海量日志文件,查询模式高度集中在"扫一大批数据、算几个指标"。
- 2016 年开源。从"一个算子"长成"一个完整的列式 OLAP 数据库",但骨子里的取向没变:为大规模的读和聚合服务,而不是为一条一条地改数据服务。
- 2024 年,团队在 VLDB 发表了第一篇学术论文(Lightning Fast Analytics for Everyone),把架构完整讲了一遍。这篇论文的网页版就是官网上 Architecture overview 那一页——本系列很多架构性描述都以它为准。
还有一个容易被忽略的工程事实:ClickHouse 是用 C++ 写的单一静态链接二进制,不依赖 JVM。这不是炫技,它直接决定了三件事——没有 GC 停顿、可以压榨 SIMD 指令、部署起来就是一个可执行文件。对延迟敏感的分析场景,这三点都是实打实的收益。
1.1.2 快在哪:五个能说清楚的机制
"快"这个字太笼统,拆开看其实是五个机制叠加的结果。下表是本系列的归纳,每一项都能在官方 concepts 板块找到对应章节。
| 机制 | 通俗解释 | 官方对应位置 |
|---|---|---|
| 列式存储 | 查询只读用到的列,其余列的数据根本不碰,I/O 直接少一个数量级 | Concepts / 架构总览 |
| 向量化执行 | 一次处理一批值(而不是一行),CPU 缓存命中率高,还能借 SIMD 加速;配合机会式代码编译进一步提速 | 架构总览(MonetDB/X100 模型) |
| 激进的数据裁剪 | 分区裁剪 + granule 跳过 + 跳过索引(skipping index),让引擎尽量少读无关数据 | Concepts / Primary indexes、Best Practices |
| 稀疏主键索引 | 主键索引不是"每行一条",而是"每 8192 行一条",索引小到能常驻内存,查找快 | Concepts / Primary indexes |
| part + 后台 merge | 写入生成不可变的 part,后台持续合并成大 part,写入不阻塞查询 | Concepts / Table parts、Table part merges |
这五点里,"稀疏主键索引"和"part 不可变"是最容易被从 MySQL 转过来的人误解的两点,我们后面第 3、4 章会专门拆开讲。
一句话总结这一节的性格:ClickHouse 把"读"优化到极致,代价是把"改"和"事务"做得比较克制。记住这句话,第 1.4 节的反场景清单就顺理成章了。
1.1.3 和常见数据库的差别,一张表说清
很多人第一次接触 ClickHouse 会问:"它和 MySQL 有什么区别?和传统数仓有什么区别?"下表给一个粗粒度的对照,具体到语法和引擎的差异,后面章节再展开。
| 维度 | MySQL | ClickHouse | 传统 MPP 数仓 |
|---|---|---|---|
| 存储组织 | 行存为主 | 列存 | 列存 |
| 主打场景 | OLTP 事务、点查点写 | OLAP 大宽表扫描聚合 | OLAP 分析 |
| 更新方式 | 行级即时更新 | 批量 mutation / 轻量更新,非即时 | 批量 |
| 事务能力 | 完整 ACID、多语句事务 | part 级原子写入,非多语句事务 | 视产品而定 |
| 并发模型 | 高并发短查询 | 高并发分析查询(依托裁剪 + 缓存) | 中高并发 |
| 存算形态 | 单机/主从 | 单机 / 集群分片副本 / Cloud / 本地工具 | 集群 |
| 部署依赖 | 一般需运维栈 | 单个静态二进制,无 JVM | 通常较重 |
1.2 三层架构一眼看全
ClickHouse 的官方架构描述把引擎拆成三层,外加一圈旁路能力。一图先看全貌,再逐层说。
ClickHouse 引擎分层 ────────────────────────────────────────────────────────────────────── 输入方言:SQL / PRQL / KQL ────────────────────────────────────────────────────────────────────── [① 查询处理层 Query Processing] 解析 → 构建并优化逻辑计划/物理计划 → 执行 执行模型:向量化执行 (MonetDB/X100 模型) + 机会式代码编译 │ ▼ [② 存储层 Storage] • MergeTree* 家族 —— 主持久化格式(基于 LSM 思路) • 专用引擎 (special-purpose) —— Dictionary / Distributed / Memory • 虚拟引擎 (virtual) —— 与外部系统双向交换数据 │ ▼ [③ 集成层 Integration] 关系数据库 / 消息系统 / KV 存储 / 数据湖 / 对象存储 ────────────────────────────────────────────────────────────────────── 旁路能力:访问层(会话与协议) · 线程管理 · 缓存 · RBAC 权限 · 备份恢复 · 持续监控 ──────────────────────────────────────────────────────────────────────① 查询处理层:负责把一条 SQL 变成可执行的计划。和很多数据库不同的是,它的执行模型是向量化的——不是一行一行算,而是一批一批(block)地算。这套模型来自 MonetDB/X100,是分析型数据库高性能的通用答案;ClickHouse 在此基础上还叠加了机会式代码编译,把热点表达式当场编译成机器码。
② 存储层:这是 ClickHouse 的"心脏",也是本系列花篇幅最多的地方。表引擎分三类,这个分类非常好用,后面判断任何一个引擎属于哪一类都能套:
- MergeTree* 家族:ClickHouse 的原生、主持久化格式。基于 LSM 树的思路:表被切成按主键有序的水平 part,后台进程持续合并。家族成员的区别只在于"合并时怎么处理输入 part 的行"——比如合并成聚合值(
SummingMergeTree)、保留最新(ReplacingMergeTree)。 - 专用引擎(special-purpose):用来加速或分发查询。典型代表是
Dictionary(把外部数据源的查询结果缓存起来当字典用,容忍一定数据陈旧的前提下大幅降低访问延迟)、Distributed(给多个分片提供一个全局视图)、Memory(内存引擎,常用于临时表)。 - 虚拟引擎(virtual):用于和外部系统双向交换数据。关系库(MySQL、PostgreSQL)、发布订阅系统(Kafka、RabbitMQ)、KV 存储(Redis)、数据湖(Iceberg、DeltaLake、Hudi)、对象存储(S3、GCS)都在这类里。第 10~14 章的集成,绝大多数都落在这一层。
③ 集成层:把上面那批"虚拟引擎"能对接的系统统称为集成层。ClickHouse 不试图把数据都搬到自己的存储里,而是允许你以表函数、表引擎或数据库引擎三种粒度去读写外部数据——这一点在湖仓场景里非常关键(第 13 章 Paimon 就靠它)。
旁路能力:不在三层主线上,但生产环境一个都不能少——访问层(管会话和协议)、线程管理、各类缓存、基于角色的访问控制(RBAC)、备份恢复、持续监控。它们分别对应第五篇的第 15~17 章。
1.3 五种部署形态与四种接入协议
同一套引擎,可以在差别很大的形态下运行。搞清楚这五种形态,能帮你在"本地验证"“生产部署”"临时分析"之间快速选对工具。
| 部署形态 | 一句话说明 | 典型用途 | 官方叫法 |
|---|---|---|---|
| 自托管(on-premise) | 自己装单机或集群,配分片 + 副本 | 生产主力形态 | on-premise mode |
| 云托管(ClickHouse Cloud) | 全托管、自动伸缩的 DBaaS | 不想自己运维时 | cloud mode |
| 单机工具(clickhouse-local) | 命令行工具,把 ClickHouse 当cat/grep的 SQL 替代品 | 本地分析文件、临时验证 | standalone mode |
| 进程内嵌(chDB) | 把 ClickHouse 作为 OLAP 引擎嵌进宿主进程 | Jupyter / Pandas 交互分析 | in-process mode |
| 集群(sharding + replication) | 多个节点分片,每分片可多副本 | 超过单机容量、要容灾 | sharded & replicated |
其中分片(sharding)和副本(replication)是两个正交的维度:分片解决"数据超过单机容量"(把表按分片表达式切成互相独立的子表,典型场景是几十 TB 以上),副本解决"节点故障容灾"(ReplicatedMergeTree*引擎配合 Keeper 保证每个分片始终有指定数量的副本)。Keeper 是 ClickHouse 自研的、用 C++ 写的 Raft 协调组件,定位是 ZooKeeper 的 drop-in 替代。
接入协议有四种,都用同一套引擎,只是线上跑的车不同:
| 协议 | 端口(默认) | 特点 | 适用 |
|---|---|---|---|
| Native(原生 TCP) | 9000 | Columnar 二进制传输,最省带宽、功能最全 | 客户端、大批量导入导出 |
| HTTP REST | 8123 | 任何能发 HTTP 的语言都能用,最好穿透 | Web 应用、脚本、临时调试 |
| MySQL wire | 可配置 | 复用 MySQL 客户端/驱动 | 迁移过渡、兼容现有 MySQL 工具链 |
| PostgreSQL wire | 可配置 | 复用 PG 客户端/驱动 | 兼容现有 PG 工具链 |
端口号是最容易记混的:HTTP 是 8123,Native 是 9000。第 2 章讲环境搭建时会用这两个端口做连通性验证。
1.4 能力边界:什么时候该用,什么时候别碰
一个技术教程如果只讲"它多好",那是不负责任的。ClickHouse 的能力边界其实非常清晰,因为它的设计目标是主动取舍出来的,不是能力缺失。
1.4.1 官方给的五个设计目标,反过来就是适用场景
VLDB 论文里把 ClickHouse 要解决的挑战归纳成五条,这五条基本就是它的"适用清单":
- 超大数据量 + 高写入速率:PB 级、持续高速或突发写入,同时还要能对历史数据做后台聚合/归档而不拖慢查询;
- 高并发 + 低延迟:大量查询同时跑,还要各自拿到亚秒级响应,并且能按优先级分配 CPU/内存/磁盘/网络;
- 异构数据源开放:能读写任意系统、任意位置、任意格式的外部数据;
- 好用的查询语言 + 性能内省:SQL 方言功能丰富(支持嵌套类型、窗口函数等),并且能深入分析单条查询的性能;
- 工业级健壮 + 多样部署:支持副本容灾,能跑在从旧笔记本到高性能服务器上,且以原生二进制部署。
对照你的需求,只要命中的是"读多写少、批量写、按列聚合、要快",ClickHouse 基本都会是加分项。
1.4.2 反场景清单:这些坑要提前避开
下面这些是"用了会难受"的场景,本系列把它们集中列出来,省得你踩了才回头。其中前四条是官方文档明确写明的设计取舍,后三条是本系列的实践判断(非官方原文)。
| 反场景 | 原因 | 官方 / 判断 |
|---|---|---|
| 频繁的行级点更新(OLTP 风格) | UPDATE/DELETE走的是 mutation 或轻量更新:mutation 会重写整列、I/O 很重;轻量更新也不是即时可见 | 官方(Updates 概述) |
| 需要存储过程/控制流逻辑 | ClickHouse明确不支持带IF/ELSE、循环的传统存储过程,这是基于分析型数据库定位的有意设计 | 官方(存储过程与查询参数) |
| 多语句事务 / 复杂回滚 | 只有 part 级的原子写入,没有多语句事务隔离;需要多表一致性时要靠暂存表 + 分区级操作绕 | 官方 + 判断 |
| 高频小事务型点查 | 没有行级锁,混合读写模式会很难受 | 判断(源自官方更新模型) |
| 复杂的多表 JOIN 为主 | 官方最佳实践直接建议"尽量减少并优化 JOIN",能反范式就反范式 | 官方(Best Practices) |
| 强一致的读后写 | 写入到可见、副本同步存在延迟窗口,需按业务容忍度设计 | 判断 |
| 频繁 upsert 的维表 | 官方明确"频繁更新、需近实时更新的数据应避免反范式",upsert 也不是强项 | 官方(反范式指南) |
一句话记法:ClickHouse 是"写一次、读很多次、按列大范围算"的引擎;凡是"改很多次、按行精确找、要求事务"的活,交给 MySQL 这类库去做。这也正是第 1.5 节"分工"的逻辑起点。
1.5 与核心技术组合的生态分工
现在把本系列的限定组合摆上台面。先明确一个立场:这五个系统不是 ClickHouse 的替代品,而是它的上下游。ClickHouse 在中间做分析核心,五个系统各自负责自己擅长的那一段。
数据源 / 上下游 ClickHouse 侧的接入通道 ─────────────────────────────────────────────────────────────────────────────────────── Kafka 实时消息 / 事件流 ──► Kafka 表引擎(可读可写) / Kafka Connect Sink / ClickPipes MySQL 业务库 (OLTP) ──► MySQL 表引擎(SELECT + INSERT 双向) / MySQL 数据库引擎 / ClickPipes CDC Flink 流式计算 ──► flink-connector-clickhouse(官方 Sink) Paimon 湖仓表 (冷数据) ──► Paimon 表引擎 / paimon() 表函数 —— 实验性·只读 Doris 另一套 OLAP 引擎 ──► ClickHouse 侧无官方直连;反向由 Doris JDBC Catalog 读 ClickHouse逐条说明分工与"官方支持到什么程度"——这几个结论是本系列反复取证后确认的,请务必按官方现状理解:
| 系统 | 在组合里的角色 | 与 ClickHouse 的通道 | 状态 |
|---|---|---|---|
| Kafka | 实时数据总线:业务 CDC、日志、事件先汇入 Kafka | ① Kafka 表引擎(OSS 自带,可读可写,自托管首选)② Kafka Connect Sink(clickhouse-kafka-connect)③ ClickPipes for Kafka(云托管) | 官方(三种通道) |
| MySQL | 业务真源:交易的"系统 of record" | ① MySQL 表引擎(ENGINE = MySQL(...),SELECT + INSERT 双向)② MySQL 数据库引擎(转发查询,支持SHOW TABLES)③ ClickPipes for MySQL CDC(云,public beta) | 官方(表引擎/数据库引擎/ClickPipes) |
| Flink | 流式加工:清洗、维表关联、窗口聚合 | 官方连接器仓库github.com/ClickHouse/flink-connector-clickhouse | 官方(Core 集成) |
| Paimon | 湖仓冷数据:低成本对象存储上的明细/历史表 | Paimon 表引擎(PaimonS3/PaimonAzure/PaimonHDFS/PaimonLocal)+paimon()表函数,支持快照读、增量读、分区裁剪 | 实验性 · 只读(需开启实验开关) |
| Doris | 另一套 MPP OLAP:可做分工或迁移对照 | ClickHouse 侧没有官方 Doris 直连引擎;反向有 Doris 的 JDBC Catalog 可以读 ClickHouse | 反向通道(非 ClickHouse 官方) |
两个必须把丑话说在前面的点:
- Paimon 通道是"实验性 + 只读"。它不是"Paimon 和 ClickHouse 完整双向打通",而是"ClickHouse 能只读地把 Paimon 表当数据源来读"。所以如果你想"从 ClickHouse 反向写回 Paimon"是走不通的,得绕 Flink。第 13 章会把这个通道的参数、限制逐条讲透。
- Doris 通道不在 ClickHouse 官方集成清单里。所以本系列不会虚构一个"Doris 引擎"。第 14 章讨论的是两套 OLAP 的分工、协同与迁移评估,桥接手段是"经 Flink 双写"或"经 Kafka 双订阅",以及反向用 Doris 的 JDBC Catalog 读 ClickHouse。
一个历史坑:早期有一条
MaterializedMySQL复制引擎,能像"拉取 MySQL 变更"一样把数据同步进来。据 ClickHouse 版本变更记录,它已被官方弃用并从 24.12 版本起移除(此条本系列标注为待第 11 章以官方原文复核)。如果你还看到老教程让你用它,请直接改用 Flink CDC / ClickPipes CDC 的路线。
1.6 五分钟眼见为实
理论讲完,先动手感受一下。这一节不需要装任何东西——我们用两种"零安装"方式跑通第一条查询。完整的单机/集群安装放到第 2 章。
1.6.1 方式一:官方在线 Playground(最快,只读)
打开 ClickHouse 官方提供的在线 Playground(只读实例,地址以官网当前提供的为准),在查询框里粘贴下面这段,直接运行:
SELECTnumber%10ASbucket,-- 0~9 十个桶count()ASrows_count,-- 每桶行数round(avg(number),2)ASavg_value-- 每桶平均值FROMnumbers(100000000)-- 1 亿行GROUPBYbucketORDERBYbucket;numbers(N)是 ClickHouse 内置的表函数,会生成 0 到 N-1 的整数序列——用它做基准非常方便。这段查询要扫 1 亿行并分组,返回结果如下(数值可由等差数列推出,与机器无关;耗时因环境而异,一般是毫秒级到百毫秒级):
┌─bucket─┬─rows_count─┬──avg_value─┐ │ 0 │ 10000000 │ 49999995.00 │ │ 1 │ 10000000 │ 49999996.00 │ │ 2 │ 10000000 │ 49999997.00 │ │ 3 │ 10000000 │ 49999998.00 │ │ 4 │ 10000000 │ 49999999.00 │ │ 5 │ 10000000 │ 50000000.00 │ │ 6 │ 10000000 │ 50000001.00 │ │ 7 │ 10000000 │ 50000002.00 │ │ 8 │ 10000000 │ 50000003.00 │ │ 9 │ 10000000 │ 50000004.00 │ └────────┴────────────┴────────────┘ 10 rows in set. Elapsed: 0.0xx sec. Processed 100.00 million rows.注意最后那行Processed 100.00 million rows——这是 ClickHouse 的标志性提示,它会明确告诉你"我到底扫了多少行"。这种对处理量的坦诚,是后面做性能调优的重要抓手(第 15 章会讲怎么用system.query_log把它用起来)。
1.6.2 方式二:clickhouse-local(本地真跑一张 MergeTree 表)
如果你已经装了clickhouse可执行文件(安装包里自带clickhouse-local),可以直接在命令行做单机分析,不用起服务:
# 单条查询:同样不落盘、不进服务clickhouselocal--query"SELECT count() FROM numbers(100000000)"输出:
100000000接着我们建一张真实的 MergeTree 表——用一组车联网上报数据做例子,正好贴合本系列的实战场景。启动交互式会话:
clickhouselocal进入后会看到:)提示符(版本号以你本地为准)。依次执行下面四步。
第一步:建表。这是本教程的第一个CREATE TABLE,请留意ENGINE = MergeTree与ORDER BY这两处——它们决定了数据在磁盘上怎么排、索引怎么建。
CREATETABLEvehicle_events(event_timeDateTime,-- 上报时间vin String,-- 车辆识别码speed Float32,-- 车速 km/hsoc UInt8-- 剩余电量 %)ENGINE=MergeTreeORDERBY(vin,event_time);第二步:插入示例数据。
INSERTINTOvehicle_eventsVALUES('2026-10-24 08:00:00','LSVAA1234A0000001',62.5,88),('2026-10-24 08:00:05','LSVAA1234A0000001',65.0,87),('2026-10-24 08:00:10','LSVAA1234A0000001',0.0,86),('2026-10-24 08:00:00','LSVAA1234A0000002',41.2,73),('2026-10-24 08:00:05','LSVAA1234A0000002',44.8,72),('2026-10-24 08:00:10','LSVAA1234A0000002',50.1,71),('2026-10-24 08:00:15','LSVAA1234A0000002',53.4,70);第三步:查表结构。DESCRIBE可以看到我们定义的四个字段及其类型,这是后面讲数据类型选型(第 5 章)的起点。
DESCRIBETABLEvehicle_events;┌─name───────┬─type─────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐ │ event_time │ DateTime │ │ │ │ │ │ │ vin │ String │ │ │ │ │ │ │ speed │ Float32 │ │ │ │ │ │ │ soc │ UInt8 │ │ │ │ │ │ └────────────┴──────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘第四步:做一次 GROUP BY 聚合。按车辆分组,算样本数、平均车速、最低电量:
SELECTvin,count()ASsamples,round(avg(speed),1)ASavg_speed,min(soc)ASmin_socFROMvehicle_eventsGROUPBYvinORDERBYvin;┌─vin───────────────┬─samples─┬─avg_speed─┬─min_soc─┐ │ LSVAA1234A0000001 │ 3 │ 42.5 │ 86 │ │ LSVAA1234A0000002 │ 4 │ 47.4 │ 70 │ └───────────────────┴─────────┴───────────┴─────────┘结果对得上手算:LSVAA1234A0000001的速度是 62.5、65.0、0.0,平均 42.5;LSVAA1234A0000002是 41.2、44.8、50.1、53.4,平均 47.375 四舍五入到 47.4。
1.6.3 顺手看一眼"part"到底是什么
这是本章最想让你带走的一个观察。ClickHouse 每次INSERT都会在磁盘上生成一个新的、不可变的 part。查一下:
SELECTname,rows,formatReadableSize(bytes_on_disk)ASsize,activeFROMsystem.partsWHEREtable='vehicle_events';┌─name────────┬─rows─┬─size──────┬─active─┐ │ all_1_1_0 │ 7 │ <随版本> │ 1 │ └─────────────┴──────┴───────────┴────────┘说明:
size列由formatReadableSize(bytes_on_disk)生成,具体字节数随版本、压缩设置和列编码而变化,没有固定值,这里不必记具体数字;你只需要确认它非零、rows等于你写入的行数即可。
我们只插了一次,所以只有一个 part(名字里的all_1_1_0大致含义是"覆盖全部,第 1 到第 1 个块,合并层级 0")。如果你再执行一次INSERT,这里会变成两个 part,而后台合并进程(merge)会择机把它们合并成一个。这个"写入即生成 part、后台持续 merge"的模型,正是第 3 章的主角。active = 1表示这个 part 当前对查询可见——被合并掉的旧 part 会先置为不活跃,等没有查询引用它之后再删除。
到这里,你已经用五分钟走完了一次"建表 → 写入 → 聚合查询 → 观察物理存储"的完整闭环。剩下 19 章,就是把这条链路上的每一环拆开、做深、做稳。
1.7 工程要点
把本章的结论沉淀成几条能带走的工程判断:
- 定位先于语法。在写第一行建表语句之前,先判断业务是"读密集"还是"写密集"。前者交给 ClickHouse,后者交给 MySQL——这个判断错了,后面再怎么调优都是逆风。
- "快"是五个机制叠出来的,不是玄学。列存、向量化、裁剪、稀疏索引、part+merge,任何一次性能优化,本质上都是在让这五个机制更好地发挥作用。
- 三层架构是排查问题的坐标系。遇到问题先问"它属于查询处理层、存储层还是集成层",能立刻缩小范围——比如查询慢多半在查询层/存储层,连不上外部系统多半在集成层。
- 部署形态和接入协议要按场景选,不要默认为"起个集群"。临时分析用
clickhouse-local,本地验证用单机,生产再上集群 + 副本;应用侧没装原生驱动就用 HTTP 8123。 - 集成能力"支持到什么程度",必须回到官方集成页确认。本章已经标出两个易踩的坑:Paimon 是实验性只读、Doris无官方直连。老教程里的
MaterializedMySQL也已经是历史。 - 反场景要提前避,而不是出事再改。点更新、事务、复杂 JOIN、强一致读后写——这几类需求在选型阶段就该排除在 ClickHouse 之外。
1.8 本章小结
- ClickHouse 是一款为分析而生的列式 OLAP 数据库:2009 年从 Yandex 的日志分析算子起步,2016 年开源,2024 年有 VLDB 论文背书,C++ 单一静态二进制、无 JVM。
- 它的"快"来自列存 + 向量化执行 + 激进裁剪 + 稀疏主键索引 + part/merge五个机制的叠加;它的"克制"则集中在更新与事务——这是主动取舍。
- 架构可拆成查询处理层 / 存储层 / 集成层三层,外加访问、缓存、RBAC、备份、监控等旁路能力;存储层的表引擎分MergeTree* 家族、专用引擎、虚拟引擎三类。
- 部署有自托管 / 云 / 单机工具 / 进程内 / 集群分片副本五种形态,接入有Native / HTTP / MySQL wire / PostgreSQL wire四种协议(HTTP 8123、Native 9000)。
- 与本系列五大组合的分工已经画清:Kafka 是实时总线、MySQL 是业务真源、Flink 做流式加工、Paimon 是湖仓冷数据、Doris 是另一套 OLAP;其中 Paimon 通道为实验性只读,Doris 侧无官方直连。
- 最后用零安装方式跑通了建表 → 写入 → 聚合查询 → 观察 part的完整闭环。
1.9 下章预告
第 1 章让你"知道它是什么",第 2 章开始"把它装起来、连上去"。下一章我们会系统性解决三件事:
①版本体系——ClickHouse 用的是"年份版本号"(如 26.x),这和 MySQL/Oracle 的语义化版本完全不是一套逻辑,选版本、看 Release Note、判断兼容性都要按这套来;
②环境搭建——从单机自托管到集群(分片 + 副本)的完整步骤,包括配置目录、config.xml、副本宏{uuid}/{replica}的写法,以及 ClickHouse Keeper 的部署;
③客户端与接口——clickhouse-client、HTTP 8123、Native 9000 三条连通性验证路径,以及各语言客户端的选型。装好环境、跑通连接之后,第 3 章才会正式进入 ClickHouse 的存储内核。
1.10 官方参考资料
| 主题 | 官方链接 |
|---|---|
| Concepts 总览(三大板块) | clickhouse.com/docs/concepts |
| 架构总览(VLDB 2024 论文网页版) | Concepts / Architecture overview |
| VLDB 2024 论文原文 PDF | p3731-schulze.pdf |
| 稀疏主键索引 | Concepts / Primary indexes |
| 表部件 table parts | Concepts / Table parts |
| 表部件合并 | Concepts / Table part merges |
| 查询并行 | Concepts / Query parallelism |
| 集成总览 | clickhouse.com/docs/integrations |
| Kafka 集成 | Integrating Kafka with ClickHouse |
| MySQL 集成 | MySQL integration |
| Paimon 表引擎 | Paimon table engine |
| Flink 连接器(官方仓库) | github.com/ClickHouse/flink-connector-clickhouse |
| 存储过程与查询参数(不支持控制流) | Stored procedures and query parameters |
| 更新机制概览 | Updates in ClickHouse |
| 最佳实践:反范式 | Denormalizing Data |
1.11 版本取证说明
本章涉及的事实按取证通道说明如下,凡未直接引到官方原文的均已标注:
- ClickHouse 出身与架构描述(2009 年起源于日志分析算子、2016 年开源、C++ 单一静态二进制、查询/存储/集成三层 + 访问层、向量化模型 MonetDB/X100、机会式代码编译、表引擎三类、Keeper 是 ZooKeeper 的 drop-in 替代、五种部署形态、四种接入协议)——均取自官方Architecture overview(VLDB 2024 论文网页版),链接见 1.10。
- "为分析而生"的五个设计目标——VLDB 论文 INTRODUCTION 章节的归纳,属官方原文。
- 更新机制(mutation / 轻量更新)与"不支持存储过程控制流"——分别取自官方Updates 概述与存储过程与查询参数页,属官方原文。
- 集成通道(Kafka 三通道、MySQL 表引擎双向 + 数据库引擎 + ClickPipes CDC、Flink 官方连接器、Paimon 实验性只读表引擎)——取自官方集成总览及其子页,属官方原文。
MaterializedMySQL已被官方弃用并从 24.12 移除——本章未直接引到官方原文,标注为"据版本变更记录",待第 11 章以官方迁移/变更文档复核。- Doris 无官方直连——基于官方集成清单的反证(清单中不存在 Doris 条目),非官方正面声明;反向的"Doris JDBC Catalog 读 ClickHouse"属 Doris 侧能力,以 Doris 文档为准。
- 版本号体系为年份版本(26.x)——来自官方页面中出现的版本表述(如"From ClickHouse version 26.9 onwards"“versions 26.1 to 26.8”),本章仅作体系说明,具体选用版本请在部署时以官方 Release Note 为准。
- 本教程
clickhouse-local演示:查询结果(numbers(100000000)的分组聚合值、vehicle_events的聚合值)可由算术推导得出,与机器无关;system.parts中的字节数、各查询实际耗时随环境与版本变化,文中未给固定值。示例数据中的 VIN、时间均为虚构样例。
1.12 实操清单
以下操作全部可在零安装或最小安装前提下复现,建议边读边做:
| # | 操作项 | 关键命令 / SQL | 预期结果 | 对应小节 |
|---|---|---|---|---|
| 1 | 在线跑通第一条聚合查询 | SELECT number%10, count(), avg(number) FROM numbers(100000000) GROUP BY 1 | 返回 10 行、每行 1000 万,并提示Processed 100.00 million rows | 1.6.1 |
| 2 | 本地单机查询(不起服务) | clickhouse local --query "SELECT count() FROM numbers(100000000)" | 输出100000000 | 1.6.2 |
| 3 | 建第一张 MergeTree 表 | CREATE TABLE vehicle_events (...) ENGINE = MergeTree ORDER BY (vin, event_time) | 建表成功,无报错 | 1.6.2 |
| 4 | 插入样例数据 | INSERT INTO vehicle_events VALUES (...) | 插入 7 行成功 | 1.6.2 |
| 5 | 查看表结构 | DESCRIBE TABLE vehicle_events | 返回 4 个字段及类型 | 1.6.2 |
| 6 | 分组聚合查询 | SELECT vin, count(), round(avg(speed),1), min(soc) FROM vehicle_events GROUP BY vin | 返回 2 行,平均车速 42.5 / 47.4 | 1.6.2 |
| 7 | 观察物理 part | SELECT name, rows, active FROM system.parts WHERE table='vehicle_events' | 返回 1 个 part、7 行、active=1 | 1.6.3 |
| 8 | 再插一次,观察 part 增长 | 再次执行第 4 步的INSERT | system.parts出现第 2 个 part,后台合并后会减少 | 1.6.3 |
思考题(下章前想清楚,带着问题读第 2 章):
- 你的业务里,哪些查询是"读多写少、按列聚合"的?哪些是"频繁改、按行找"的?请各举一例。
- 如果只用 HTTP 8123 就能接入 ClickHouse,为什么生产环境还常常推荐 Native 9000?
本章完。下一章:第 2 章 环境搭建、版本体系与客户端接口。