Gluten + Velox 是什么?Spark 向量化执行为什么能提速?
技术点:向量数据库
面试怎么回答
Spark 原生执行是 JVM 上按行处理,虽然有 Whole-Stage Codegen,但很难利用 SIMD,还有对象和 GC 开销。Gluten 是一个中间层,把 Spark 优化后的物理计划翻译成 Substrait,交给 Velox 或 ClickHouse 这样的 C++ 向量化引擎执行,数据以列式批流转,所以能用上 SIMD、没有 GC,Parquet 扫描、Join、聚合、Shuffle 都更快,公开测试大概 1.5 到 2 倍以上。最大的坑是 Fallback:不支持的算子会回退到原生 Spark,中间要做行列转换,回退多了反而更慢;还有部分函数边界行为不一致、堆外内存要单独配、UDF 无法加速。落地时先看回退统计,挑覆盖率高的重计算作业灰度,双跑比对结果,再按 CPU 成本评估收益。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
Spark SQL 经过多年优化,JVM 上的执行效率已经很难再挤出空间,于是社区开始把执行层换成 C++ 的向量化引擎。Apache Gluten(孵化中)就是其中最主流的方案。面试官问这题,想看你懂不懂 Spark 的执行瓶颈在哪,以及「换引擎」有哪些坑。
Spark 原生执行的瓶颈
- 按行处理:Spark 内部数据格式是 UnsafeRow,虽然有 Whole-Stage Codegen 把多个算子融合成一段代码,但本质上还是一行一行处理;
- 难以利用 SIMD:JVM 对 CPU 向量指令的利用很有限,无法像 C++ 那样一条指令处理一批数据;
- GC 和内存开销:大量对象和堆内存,在大数据量下 GC 也会拖慢。
Gluten 怎么做
Gluten 本身不是执行引擎,而是一个「中间层」:
- Spark 照常做 SQL 解析和优化,得到物理计划;
- Gluten 把物理计划翻译成 Substrait(一种跨引擎的计划描述格式);
- 交给原生后端执行:Velox(Meta 开源的 C++ 向量化执行库)或者 ClickHouse 后端;
- 数据以列式批(Columnar Batch)在算子之间流转,充分利用 SIMD 和缓存。
接入方式是以插件形式加载(spark.plugins 配 Gluten 插件),并开启堆外内存,因为原生引擎用的是堆外内存。
为什么能快
- 列式 + 向量化:一次处理一批同类型的数据,CPU 缓存命中率高,能用 SIMD;
- 原生代码:没有 JVM 的对象开销和 GC;
- 专门优化的算子:Parquet 读取、Hash Join、Hash Aggregation、Shuffle 等热点算子在 C++ 里做了深度优化。
官方和一些公司公布的 TPC-H / TPC-DS 测试大致是整体 1.5~2 倍以上的提升,但实际收益取决于你的作业有多少能完全跑在原生引擎里。
一定要注意的坑:Fallback
- 不支持的算子或函数会回退到原生 Spark,比如某些 UDF、少见的表达式;
- 回退处要做列转行 / 行转列(ColumnarToRow / RowToColumnar),转换本身有开销,回退点多了反而比原生 Spark 还慢;
- 结果一致性:部分函数在边界情况(精度、时区、空值、正则语义)下和 Spark 原生行为可能有差异,上线前要做结果比对;
- 内存配置:堆外内存要单独规划,配少了会 OOM,配多了浪费;
- Java / Python UDF 无法向量化,UDF 多的作业收益有限。
落地建议
先用 Gluten 的 Fallback 统计找出高频回退点,挑算子覆盖率高、计算重(大 Join、大聚合、扫描 Parquet)的作业灰度;新旧引擎双跑做结果比对;对比 CPU 时间和成本,而不只看运行时长。