
1.1 背景知识
写完一个引擎远远不是终点。OLAP 的工程深水区在于优化------同样一份代码,常数项的差异可以达到 10 倍以上。
我们用 TPC-H 的简化负载评估 MiniDuck,对照 DuckDB CLI。
1.2 Benchmark 结果
数据:自造 lineitem 风格表,1000 万行,约 200MB。
| 查询 | DuckDB 1.x | MiniDuck v1 | 比值 |
|---|---|---|---|
SELECT COUNT(*) FROM t WHERE amount > 50 |
0.04 s | 0.18 s | 22% |
SELECT city_id, SUM(amount) FROM t GROUP BY city_id |
0.12 s | 0.31 s | 39% |
SELECT city_id, AVG(amount * 1.13) FROM t WHERE flag = 1 GROUP BY city_id |
0.18 s | 0.55 s | 33% |
教学版本能稳定到 DuckDB 的 30%~40%,已经远好于 SQLite/Pandas。差距主要来自下面这些"魔鬼细节"。
1.3 优化路线图

Tier 1:低成本高收益(建议读者动手)
- 列裁剪:Scan 阶段只读 SQL 涉及的列,不读其他列
- 谓词下推 :
Filter推到Scan内,扫描时直接生成 selection vector Arc<Table>:消除 clone(仓库已实现)- 复用 batch buffer :避免每次分配新
Vec #[inline]+target-cpu=native:直接用上 AVX2/AVX-512
Tier 2:进阶(需要重构)
- Selection vector 模型 :所有算子接受
(batch, sel: &[u32]),避免反复物理拷贝 - 类型特化 :对
i32/i64/f32/f64分别 monomorphize 算子,去掉dyn调度 - 多 key hash agg:用 row-format 序列化多列 key
- Parallel scan:用 Rayon 把 batch 分发到多线程
Tier 3:研究级
- Morsel-driven parallelism(HyPer 论文):动态 work-stealing 替代静态划分
- Adaptive execution:运行时切换 hash agg / sort agg
- JIT 编译 表达式:Cranelift 把热点表达式编成机器码
- Push-based execution(DuckDB 已切换):算子之间反向"推"数据
1.4 总结
我们用大约 400 行 Rust(含三方库胶水),实现了一个具备以下能力的 OLAP 引擎:
- 列式存储(Arrow 兼容) - 向量化执行 - 表达式解释器 - 哈希聚合 - SQL 解析与计划 - 性能达 DuckDB 的 30%~40%
这套架构与 DuckDB、DataFusion、ClickHouse 的内核思路一致,量级有别------理解了 MiniDuck,再去读这些工业级引擎的源码会顺畅得多。
1.5 终极自测
- 你能徒手画出 MiniDuck 从 SQL 字符串到结果输出的完整数据流吗?标出每一步的输入/输出类型
- 如果让你给 MiniDuck 加 JOIN,你会优先实现 Hash Join 还是 Merge Join?为什么?
- 列出至少 5 个 MiniDuck 与生产级 OLAP 引擎的差距
- 如果要把 MiniDuck 改造成"分布式",最先遇到的瓶颈是什么?参考 Presto、ClickHouse、Snowflake 的不同选择
1.6 拓展学习
- DuckDB 团队博客 duckdb.org/news,每篇文章都是一个优化点深挖
- DataFusion 是用 Rust 写的"工业级版 MiniDuck",强烈建议作为下一站
- 论文:Photon: A Fast Query Engine for Lakehouse Systems(Databricks,SIGMOD 2022)
- 视频:CMU 15-721 Advanced Database Systems,全网最系统的 OLAP 内核课程
配套仓库使用
下载并解压 miniduck.zip:
bash
unzip miniduck.zip && cd miniduck
cargo build # 编译
cargo test # 集成测试 4/4
cargo run --example ch1_table # 第 1 章 demo
cargo run --example ch2_scan # 第 2 章 demo
cargo run --example ch3_filter # 第 3 章 demo
cargo run --example ch4_agg # 第 4 章 demo
cargo run --example ch5_sql # 第 5 章 端到端 SQL
cargo bench # 第 6 章 benchmark
仓库结构:
python
miniduck/
├── Cargo.toml
├── README.md
├── src/
│ ├── lib.rs
│ ├── storage.rs # Ch1
│ ├── exec.rs # Ch2
│ ├── expr.rs # Ch3
│ ├── agg.rs # Ch4
│ ├── catalog.rs # Ch5
│ └── planner.rs # Ch5
├── examples/
│ ├── ch1_table.rs
│ ├── ch2_scan.rs
│ ├── ch3_filter.rs
│ ├── ch4_agg.rs
│ └── ch5_sql.rs
├── benches/
│ └── tpch_lite.rs # Ch6
└── tests/
└── integration.rs
Happy hacking! 完成本教程后,下一步建议直接阅读 DataFusion 源码------它就是这套架构的工业级实现,1.5 万星 Rust 项目。