列存引擎内核 — 系列规划
本文是写作规划,不是可发布正文。主选 ClickHouse 作为拆解对象,DuckDB 作为嵌入式/OLAP 对照;不写泛泛的「列存概念」科普。
一、为什么写这个系列
1.1 存储引擎三角的缺口
| 已有内容 | 引擎类型 | 视角 |
|---|---|---|
postgresql-kernel/ (26) |
行存 OLTP | B-Tree + MVCC + WAL |
db/lsm-tree/ (9) |
写优化 LSM | MemTable + SSTable + Compaction |
storage/ (79) |
通用原理 | 含列存概念但未落到具体实现 |
db-frontier/ (25) |
AI 原生 DB 前沿 | 向量/HTAP,非经典列存内核 |
结论:读者理解行存(PG)和写优化(LSM)后,缺 读优化列存 的完整源码级拆解。ClickHouse 是开源列存工程标杆;DuckDB 代表「嵌入式分析」路径——两者对照覆盖 OLAP 主战场。
1.2 为什么选 ClickHouse(主)+ DuckDB(辅)
| 维度 | ClickHouse | DuckDB |
|---|---|---|
| 源码 | C++,结构清晰,MergeTree 家族完整 | C++11,向量化执行教科书 |
| 文档 | 官方 MergeTree 文档详尽 | 官方 Internals 文档 |
| 生产案例 | 国内大量 OLAP/日志分析 | 数据科学、SQLite 替代分析 |
| 与 PG 关系 | 常作 PG 分析副本/外表 | pg_duckdb 扩展兴起 |
| 系列篇幅 | 主系列 15–18 篇 | 3–4 篇对照/专题 |
1.3 系列定位
列存 = 存储布局 + 向量化执行 + 合并策略 + 分布式(可选)
不写 SQL 教程,写: - 为什么列存 scan 1 列比行存读整行快(含 CPU cache / SIMD) - MergeTree part 如何 merge、为什么 merge 是列存的心脏手术 - PRIMARY KEY 在 ClickHouse 里不是唯一约束——排序键语义 - 向量化 volcano vs 向量批处理(morsel-driven)
二、核心问题与目标读者
2.1 六个关键问题
列存文件在磁盘上长什么样? → 第 1、2 章:Part、Column、Mark、Granule、压缩块。
一次 SELECT 如何从 part 读到向量批? → 第 3、4 章:Read path、Mark Range、PREWHERE、向量化执行。
MergeTree 的 merge 到底在合并什么? → 第 5、6 章:Merge 算法、TTL、Mutation vs Merge。
ClickHouse 的「索引」是什么? → 第 7 章:稀疏主键索引、跳数索引(minmax/set/bloom)、与 B-Tree 的本质差异。
分布式表如何工作? → 第 8、9 章:Local table、Distributed、ReplicatedMergeTree、ZooKeeper/ Keeper 协调。
列存生产环境会出什么事故? → 第 14–16 章:Parts 过多、merge 跟不上、mutation 阻塞、副本延迟、内存 OOM。
2.2 目标读者
- 数据平台工程师、OLAP 开发者、从 PG/MySQL 转 ClickHouse 的 DBA
- 先修:SQL、
postgresql-kernel或storage索引章节、基本 C++ 阅读能力 - 不假设:已有 ClickHouse 运维经验
三、篇目结构(主系列 16 篇 + DuckDB 专题 3 篇)
第一部分:存储格式(第 1–3 章)
第 1 章:列存基础与 ClickHouse 架构
- 行存 vs 列存:带宽、压缩、向量化三角
- ClickHouse 进程模型:Server、MergeTreeBackgroundExecutor
- 表引擎概览:MergeTree 家族地图
- 源码入口:
src/Storages/、src/Databases/
第 2 章:MergeTree Part 文件格式
- Part
目录结构:
columns.txt、checksums.txt、.bin、.mrk、.idx - Column 文件:压缩块、Granule、Mark 文件语义
- 实验:
clickhouse-local建表 + 查看data/目录 - 源码:
src/Storages/MergeTree/MergeTreeDataPart*
第 3 章:压缩与编码
- LZ4、ZSTD、Delta、DoubleDelta、Gorilla(时序)
- 编码选择与列类型
- 实验:同列不同编码的压缩比 benchmark(本机,≥3 轮)
- PG 对照:TOAST 压缩 — 不同优化目标
第二部分:读取路径(第 4–7 章)
第 4 章:向量化执行引擎
- Block 结构:列向量 batch
- 算子 pipeline:filter、project、aggregate 的向量实现
- 与 volcano 模型对比(引用 PG 执行器
#12-executor) - 源码:
src/Processors/、src/Columns/
第 5 章:查询读取路径
- Mark Range 定位 Granule
- PREWHERE vs WHERE
- 并行读:
max_threads、parts 级并行 - 实验:
EXPLAIN indexes=1输出解读
第 6 章:Merge 与 Mutation
- Merge 触发条件、merge selector
- ReplacingMergeTree、CollapsingMergeTree 语义
- Mutation(ALTER UPDATE/DELETE)的异步路径与危害
- 源码:
MergeTreeDataMergerMutator
第 7 章:索引与跳数索引
- PRIMARY KEY = 排序键 ≠ 唯一
- Data Skipping Index:minmax、set、bloom_filter
- 与 PG
B-Tree(
postgresql-kernel/14-btree)对照表
第三部分:分布式与高可用(第 8–10 章)
第 8 章:ReplicatedMergeTree
- Log entry、ZooKeeper/Keeper 路径
- 副本同步、recovery
- 实验:双节点副本 + 断网观察
第 9 章:Distributed 引擎
- 分片键、分布式查询路由
- GLOBAL IN/JOIN 的代价
- 与 PG Citus / 分布式系列边界
第 10 章:物化视图与增量管道
- Materialized View 触发机制
- Kafka 引擎 + MV 典型架构
- 坑:MV 目标表引擎选择错误
第四部分:DuckDB 对照专题(第 11–13 章)
第 11 章:DuckDB 架构与嵌入式 OLAP
- 进程内、无服务器
- Storage:Row Group + Column Segment
- 与 ClickHouse 部署模型差异
第 12 章:DuckDB 向量化与 Pipeline
- Morsel-driven parallelism
- 源码:
src/execution/、src/storage/
第 13 章:ClickHouse vs DuckDB 选型
- 规模、并发、嵌入、联邦查询(pg_duckdb)
- 决策树,不排名
第五部分:运维实战(第 14–16 章)
第 14 章:监控与系统表
system.parts、system.merges、system.replication_queue- 关键指标:parts 数、merge 延迟、memory tracking
第 15 章:经典故障模式
- Too many parts
- Merge 跟不上 insert
- Mutation 堆积
- 副本延迟 / lost replica
- OOM:max_memory_usage
第 16 章:配置陷阱与容量规划
parts_to_throw_insert/parts_to_delay_insertmerge_max_block_sizemax_bytes_to_merge_at_max_space_in_pool- 磁盘:SSD vs HDD merge 策略
四、依赖关系
1 → 2 → 3 → 4 → 5
↓ ↓
6 ← 7 8 → 9
↓
10
11 → 12 → 13(DuckDB,可与 4–7 并行)
14 → 15 → 16
五、阅读路径
| 路径 | 篇目 | 适合 |
|---|---|---|
| OLAP 开发者 | 1→2→4→5→7 | 理解读写 |
| 平台/运维 | 1→6→8→14→15→16 | 集群稳定 |
| 嵌入式分析 | 11→12→13 | DuckDB |
| 从 PG 来 | 1→7→5 + PG 14 对照 | 索引语义差异 |
六、来源台账
A 级
- ClickHouse 源码(标注 release,如
24.3) - ClickHouse 官方文档:MergeTree、Replication
- DuckDB 源码 +
https://duckdb.org/docs/internals/ - 论文:MonetDB/X100(向量化)、C-Store(列存)
B 级
- Altinity / ClickHouse 官方博客(版本标注)
七、实验台账
工具 |
clickhouse-client、clickhouse-local、系统表
|数据集 |
hits 样本或
clickhouse-benchmark 默认 || 章 | 实验 |
|---|---|
| 2 | 列文件 hex 结构对照文档 |
| 3 | 编码压缩比表 |
| 5 | PREWHERE 行数对比 EXPLAIN |
| 6 | 触发 merge + 观察 system.merges |
| 8 | 副本 lag 人工制造 |
| 15 | too many parts 复现(测试环境) |
八、系列联动
| 系列 | 联动 |
|---|---|
postgresql-kernel/ |
执行器、B-Tree、监控对照 |
db/lsm-tree/ |
Compaction vs Merge 对照 |
storage/ |
压缩、块设备 |
observability/ |
日志/trace 写入 ClickHouse 场景 |
九、边界
不承诺
- 替代 ClickHouse 官方文档
- Cloud 托管版(ClickHouse Cloud)内部实现
- Spark/Flink 批流框架全文
- 实时数仓业务建模
十、写作顺序
- index.md
- 第 1、2、3 章(格式基础)
- 第 4、5 章(读路径)
- 第 6、7 章(merge 与索引)
- 第 14、15、16 章(运维,可与 8–10 交错)
- 第 8、9、10 章(分布式)
- DuckDB 11–13
十一、待确认问题
- ClickHouse 版本锚定:24 LTS?
- Keeper 替代 ZooKeeper 是否作为默认写法?
- DuckDB 3 篇是否并入主 index 还是子目录
duckdb/? - 是否增加
MergeTree以外引擎(如 S3Queue)专章?
规划版本:v1,2026-06-18
目录建议:post/db/columnar-engine/
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【列存引擎内核】ClickHouse 与 DuckDB 源码级拆解
主选 ClickHouse 拆解 MergeTree 存储格式、向量化执行与分布式协调;DuckDB 作为嵌入式 OLAP 对照。覆盖列存文件布局、merge 机制、跳数索引与生产故障模式,面向数据平台工程师与从 PG/MySQL 转 OLAP 的 DBA。