写分布式查询引擎久了,你会发现一个规律:
不管一开始你多关注 SQL 解析、多欣赏优化器、多精心设计存储层,
系统规模一上来,复杂度一定会集中爆发在 Execution Layer。
而且不是“慢慢变复杂”,而是:
- 开始返工
- 开始推翻
- 开始重写
- 开始怀疑最初的架构判断
这不是某个团队的问题,而是分布式查询引擎的工程宿命。
这篇文章,我想结合最近一段时间在 Execution Layer、Rust 实现、Shuffle、返工设计上的一些总结,聊清楚三件事:
- 为什么复杂度一定会压到 Execution Layer
- 为什么很多设计一开始看不出问题,后面却必返工
- 工程上真正值得提前“防雷”的地方在哪里
一、Execution Layer 承担的,从来不是“执行”这么简单
很多人对查询引擎的模块划分是这样的:
- SQL 解析
- 查询优化
- 执行计划
- 执行层
- 存储
但真正写过系统的人会发现,这个划分极具迷惑性。
原因在于:
- 前面的模块解决的是 静态问题
- Execution Layer 面对的是 动态、不确定、会失败的现实世界
具体来说:
- 数据分布是否均匀?——跑起来才知道
- 节点会不会慢?——运行时才发生
- 网络会不会抖?——随时可能
- 内存会不会爆?——压力上来才暴露
所有“理想假设失效”的地方,最终都会落在 Execution Layer。
这也是为什么:
- 优化器可以几年一大改
- Execution Layer 却几乎每个版本都在重构
二、Execution Layer 的复杂度,来自“不确定性的叠加”
Execution Layer 之所以难,不是因为单点问题难,而是因为多个问题会同时发生。
尤其是在以下几个场景中。
1️⃣ Shuffle:不是一个阶段,而是系统性成本放大器
从表面看,Shuffle 只是一次数据重分布:
- GROUP BY
- JOIN
- ORDER BY
但在 Execution Layer 里,Shuffle 往往意味着:
- 网络带宽被拉满
- 内存峰值不可控
- 磁盘 I/O 被迫介入
- CPU 同时承压
更危险的是:
Shuffle 会放大系统中的所有不确定性。
- 一个慢节点 → 拖垮全局
- 一次数据倾斜 → OOM
- 一次网络抖动 → 查询雪崩
很多系统的稳定性问题,最终都会追溯到 Shuffle。
2️⃣ 并发与调度:越“聪明”,越容易失控
在 Execution Layer,很多返工都源于一个误判:
“并发越高,性能越好。”
现实往往相反:
- CPU-bound 算子 async 化 → 调度成本暴涨
- 多线程 + async 混用 → 执行路径不可推理
- 并发度过高 → 资源争抢 + 尾延迟放大
在 Execution Layer,并发策略一旦选错,几乎只能推翻重来。
3️⃣ 内存与生命周期:Rust 并不会“自动帮你省内存”
Rust 的内存安全很强,但在 Execution Layer 里,常见问题并不是“内存泄漏”,而是:
- 中间结果被意外持有
- 生命周期被无意识拉长
- 内存峰值持续抬高
尤其在 Shuffle、Join、聚合场景下,一次设计失误,就可能让系统在大数据量下直接崩溃。
三、为什么 Execution Layer 的设计,最容易返工
综合来看,Execution Layer 返工,往往不是因为“代码写错了”,而是早期设计过于将就。
几个高频返工点,几乎是共性的:
❌ 执行模型不清晰
- 把查询当 SQL 字符串
- 或临时拼装执行逻辑
后期再补执行计划、算子抽象、调度模型,在 Rust 里几乎必然重构。
❌ 过度共享状态
Arc<Mutex<T>>快速实现- async + 锁 混用
初期能跑,后期性能和稳定性双双失控。
❌ 把 Shuffle 当“优化点”,而不是“风险点”
很多系统是在:
数据量上来之后,才意识到 Shuffle 根本不是“调一下参数就能救”的问题。
❌ 错误边界不清晰
- task / stage / query 错误混在一起
- panic 作为常规路径
在分布式环境下,这是事故的温床。
四、Execution Layer 工程上的“真实共识”
如果非要总结几条迟早会达成的工程共识,大概是:
- 能不 Shuffle,就不要 Shuffle
- 并发不是越多越好,而是越可预测越好
- Execution Layer 的稳定性,比极致性能更重要
- 很多优化,本质是在“止损”,不是在“提速”
Execution Layer 不是“跑算子”的地方,而是:
调度现实复杂度的地方。
结语:Execution Layer,是系统真正成熟的标志
如果你的分布式查询引擎开始在 Execution Layer 变复杂,开始返工、重构、反复推敲设计——
这通常不是坏事。
这意味着系统已经走出了“理想模型”,开始真正面对:
- 不确定的数据分布
- 不可靠的节点
- 不稳定的网络
- 不可预测的负载
Execution Layer 的复杂度,往往是一个系统进入真实世界后的必修课。
后续我也会继续围绕 Execution Layer,分享更多关于 Shuffle、调度、内存、并发和稳定性的工程经验,欢迎交流。