分布式 OLAP 查询引擎:Trino · Spark · DuckDB · 优化与 MPP 执行
读者读完 数据湖与开放表格式(表格式、Parquet、Iceberg 提交)与 流式数据处理(Kafka、Flink、入湖)之后,数据平台栈还差最后一环:交互式 SQL 如何在湖/列存/联邦源上变成物理计划、在 MPP 集群上跑起来。lakehouse 第 18 章 从「引擎如何读湖(partition/file/row-group 下推漏斗)」切入;本系列从 SQL 前端 → 逻辑/物理优化 → 执行模型 → Coordinator/Worker/shuffle → Connector 下推发起层 系统拆解。
本系列不写 SQL 语法教程,也不写 BI 选型,写:
- 一条 SELECT 从 Parser 到 Worker 上 Page 流经过哪几层 IR,CBO 如何用统计信息选 join 顺序与算法。
- Volcano pull、向量化 batch、morsel-driven 三种执行语义,以及与 列存引擎向量化执行 的衔接。
- Trino 的 Split / Stage / Task / Exchange
如何切分查询;shuffle 倾斜在 plan 与
EXPLAIN ANALYZE上长什么样。 - Spark Catalyst / AQE、DuckDB / DataFusion 嵌入式路径与 Trino 的对照边界。
- Iceberg connector 在 planner 哪一步注入 layout constraint(与 lakehouse/18 对读,不重复粘贴下推全文)。
系列状态:已完成(2026-07-07)。全 18 篇正文均已发布,可点进阅读。
版本锚定:Trino 476+;Spark 3.5+;DuckDB 1.5.4(本机实测);Iceberg table spec V2 主线。Trino/Spark 机制来自官方文档与源码路径;本机 WSL2 未部署 JVM 查询集群,DuckDB 实验见
reproduce/run_duckdb_experiments.py,Trino 栈见reproduce/docker-compose.yml。
适合谁看
- 数据平台工程师:维护 Trino/Spark 查询层,调湖上 SQL 性能与资源组。
- 从 lakehouse / stream-processing 过来的读者:已有表格式与入湖直觉,要搞清「谁在扫 manifest」。
- 从 columnar-engine / PG 内核过来的读者:有单进程优化器与执行器背景,要看分布式 MPP 多了什么。
- 架构 / 选型负责人:在 Trino、Spark、ClickHouse、DuckDB 之间做交互式分析决策。
数据平台全栈阅读顺序
| 阶段 | 系列 | 回答的核心问题 |
|---|---|---|
| 1 | PostgreSQL 内核 | 数据在进程里怎么事务、怎么 B-Tree 扫描 |
| 2 | 列存引擎 | 读优化列存怎么向量化 scan |
| 3 | Lakehouse | 数据在对象存储上怎么当表用 |
| 4 | 流式处理 | 实时管道怎么算、怎么 exactly-once 入湖 |
| 5 | 本系列 | 交互式 SQL 怎么规划、怎么 MPP 执行、怎么下推读湖 |
推荐阅读路径
| 路径 | 篇目 | 适合 |
|---|---|---|
| 数据平台全栈闭合 | 1 → 2 → 4 → 10 → 12 → 15 → 18 | 从湖仓到查询层一条龙 |
| 从 lakehouse/18 来 | 2 → 3 → 5 → 12 → 15 | planner 与下推发起层 |
| 从 columnar-engine 来 | 1 → 6 → 7 → 14 | 执行模型与嵌入式对照 |
| Trino 运维 | 1 → 10 → 12 → 16 → 17 | 调优与排查 |
| 优化器理论 | 2 → 3 → 4 → 5 → 6 | IR 与 CBO |
| 完整通读 | 1 → … → 18 | 系统掌握 |
一、六个关键问题
- 一条 SQL 从文本到 Worker 上的 Task,中间经过哪几层 IR? → 第 1、2、3 篇
- CBO 如何估 join cardinality、选 hash/broadcast join?统计错了会怎样? → 第 4、5 篇
- Volcano、向量化、morsel-driven 三种执行模型差在哪? → 第 6、7 篇
- Coordinator、Worker、shuffle、Exchange 各保证什么? → 第 10、11 篇
- Trino / Spark / DuckDB 读 Iceberg 时,下推在 planner 哪一步发起? → 第 12、15 篇(对读 lakehouse/18)
- 生产慢查询、OOM、倾斜怎么查?引擎怎么选? → 第 16、17、18 篇
二、篇目依赖
flowchart TD
A["01 OLAP 全景"] --> B["02 SQL 与逻辑计划"]
B --> C["03 Calcite 与优化框架"]
C --> D["04 统计与代价模型"]
D --> E["05 Join 与物理算子选择"]
A --> F["06 Volcano 模型"]
F --> G["07 向量化与 morsel"]
G --> H["08 Scan Filter Project"]
H --> I["09 Hash Join 与 Agg"]
A --> J["10 Coordinator Worker"]
J --> K["11 Shuffle Exchange"]
E --> L["12 Trino 全路径"]
H --> L
J --> L
L --> M["13 Spark Catalyst"]
L --> N["14 DuckDB DataFusion"]
L --> O["15 Iceberg 下推全链路"]
I --> P["16 内存 Spill 隔离"]
K --> P
L --> P
P --> Q["17 经典故障排查"]
Q --> R["18 选型与阅读地图"]
M --> R
N --> R
O --> R
跨系列:lakehouse/18 → 15;columnar-engine/04 → 07;stream-processing/01 → 01。
三、目录与每篇价值点
第一部分:查询引擎基础
- OLAP
查询引擎全景:从单进程到 MPP
- OLTP/OLAP/HTAP 边界;嵌入式 vs 分布式;数据平台栈闭合图;全系列 18 篇地图。
- SQL
解析、分析与逻辑计划
- Parser/Analyzer/Catalog;LogicalPlan 节点;DuckDB
EXPLAIN与 Trino logical plan 对照;PG parse/plan 边界。
- Parser/Analyzer/Catalog;LogicalPlan 节点;DuckDB
- Calcite
与规则/代价优化框架
- RelNode、Convention、Rule;Volcano/Cascades 搜索;Trino 自研 planner 与 Calcite 边界。
第二部分:统计与物理优化
- 统计信息与代价模型
- NDV、histogram、Iceberg manifest stats;代价模型 CPU/IO/network;统计过期与全表扫误触发。
- Join
重排与物理算子选择
- Join order;hash/merge/nested loop;broadcast vs partitioned join;DPP 与 runtime filter。
第三部分:执行模型与物理算子
- Volcano
迭代器模型
- Open/Next/Close pull 语义;pipeline breaker;PG
ExecutorRun与 Trino Operator 对照。
- Open/Next/Close pull 语义;pipeline breaker;PG
- 向量化与
morsel-driven 执行
- 列向量 batch、SelectionVector;DuckDB morsel-driven;Trino Page;链接 columnar-engine/04。
- Scan、Filter
与 Project
- ConnectorSplit/PageSource;column pruning;谓词与 limit 下推边界。
- Hash Join 与
Hash Aggregation
- Build/probe;partial/final agg;revocable memory 与 spill 触发。
第四部分:MPP 架构
- Coordinator
与 Worker 架构
- Query/Stage/Task/Driver;Split 调度与 locality;Spark Driver/Executor 对照。
- Shuffle
与 Exchange
- HASH/BROADCAST/REPLICATE;Local vs Remote exchange;倾斜判读;Spark AQE 边界。
第五部分:引擎主线与对照
- Trino
查询路径全拆解
- SqlQueryExecution 生命周期;Iceberg manifest →
Split;Page 流;
EXPLAIN ANALYZE判读。
- SqlQueryExecution 生命周期;Iceberg manifest →
Split;Page 流;
- Spark SQL
与 Catalyst
- Analyzed/Optimized/Physical;whole-stage codegen;AQE;Iceberg reader 对照。
- DuckDB
与 DataFusion
- 嵌入式分析 vs 分布式;本机 DuckDB 实测;与 columnar-engine DuckDB 篇分工。
- Iceberg
Connector 下推全链路
- Planner 视角四层漏斗;与 lakehouse/18 分工;Trino/Spark/DuckDB 能力表。
第六部分:生产与收束
- 内存、Spill
与资源隔离
- Query/user 内存账户;join/agg spill;resource group;对照 stream/18 背压。
- 经典故障与排查
- 全表扫、大 shuffle、OOM、straggler、catalog 超时;排查工具链。
- 引擎选型与数据平台阅读地图
- Trino/Spark/CH/DuckDB/PG 决策树;数据平台全栈延伸阅读;Substrait/Velox 前瞻边界。
四、与相邻系列的分工
| 话题 | 本系列 | 相邻系列 |
|---|---|---|
| Parquet row group / page 格式 | 不展开 | lakehouse/02 |
| manifest partition/file pruning 漏斗 | 第 15 篇从 planner 视角 | lakehouse/18 |
| MergeTree 向量化存储 | 不展开 | columnar-engine |
| Flink 流式 SQL / 窗口 | 不展开 | stream-processing |
| PG 进程内执行器 | 第 2、6 篇对照引用 | postgresql-kernel |
参考
- 系列规划(PLAN.md)(写作执行文档,非发布页)
- 实验复现(reproduce/)
- 数据库内核索引
- 全部系列索引
返回 数据库索引 · Lakehouse 系列 · 流式处理系列
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【分布式 OLAP 查询引擎】OLAP 查询引擎全景:从单进程到 MPP
从 OLTP/OLAP/HTAP 边界、嵌入式 DuckDB 与分布式 Trino/Spark 分工、批式扫描与交互式查询延迟口径出发,闭合 lakehouse 与 stream-processing 之间的查询层缺口,并给出本系列 18 篇地图。
【分布式 OLAP 查询引擎】Spark SQL 与 Catalyst:逻辑/物理计划与 AQE
拆解 Spark 3.5+ Catalyst 的 Analyzed / Optimized / Physical 计划链、whole-stage codegen 与 shuffle 边界、AQE 的动态 coalesce/skew join/broadcast;并与 Trino 476 及 Iceberg V2 reader 下推能力对照。
【分布式 OLAP 查询引擎】Iceberg 下推全链路:Planner 视角
与 lakehouse/18 分工:那边讲四层读湖漏斗是什么;本篇讲 Trino/Spark/DuckDB 在 SQL 优化链的哪一步把谓词变成 layout constraint、谁调用 Iceberg planning、split 如何携带残余谓词。引用官方文档与 lakehouse/18 本机 PyIceberg 实测,不伪造 Trino 计划输出。
【分布式 OLAP 查询引擎】引擎选型与数据平台阅读地图
用决策树收束 Trino/Spark/ClickHouse/DuckDB/DataFusion/PostgreSQL 的适用边界:交互式联邦、批 ETL、嵌入式分析、流批一体各走哪条路径;给出能力对照表(无吞吐排名)与 postgresql→columnar→lakehouse→stream→query-engine 全栈阅读顺序,闭合数据平台栈。