Velox 后端的限制

qianmoQqianmoQ· 更新于 2026-10-02· 阅读 9 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

本文通过列举一些已知情况来描述 Velox 后端的局限性,包括抛出异常的场景、Gluten 与 Spark 行为不兼容的情况,以及某些计划的执行必须回退到原生 Spark 等。

Spark 类的覆盖

Gluten 尽量避免修改 Spark 的现有代码,并优先使用 Spark API。然而,有些 API 并未由原生 Spark 暴露,因此我们不得不复制 Spark 的文件并进行硬编码修改。被覆盖的类列表可以在 package/pom.xml 中的 ignoreClasses 找到。如果你使用的是定制版 Spark,请检查这些文件在你的 Spark 发行版中是否已被修改,否则你的修改会被覆盖。

因此,你需要确保优先加载 Gluten 的 jar,以覆盖原生 Spark 的 jar。请参考 如何在 Spark 中优先加载 Gluten 的 jar。

如果使用了非官方支持的 Spark 版本,运行时可能会抛出 NoSuchMethodError。更多详情请参见 issue-4514。

回退

除了 中列出的不支持的算子、函数、文件格式和数据源之外,还有一些已知情况也会回退到原生 Spark。

ANSI 模式

Gluten 目前不支持 ANSI 模式。如果启用了 ANSI 模式,Spark 计划的执行将始终回退到原生 Spark。我们目前有一个 issue 用来跟踪 ANSI 支持的进展,请查看 issue-10134。

大小写敏感模式

Gluten 仅支持 Spark 默认的大小写不敏感模式。如果启用了大小写敏感模式,用户可能会得到不正确的结果。

正则函数

在 Velox 中,正则函数(rlike、regexp_extract 等)基于 RE2 实现,而在 Spark 中它们基于 java.util.regex。

  • RE2 不支持环视(前瞻/后顾)模式。
  • 当使用模式 "\s" 匹配空白字符时,RE2 不会将 "\v"(或 "\x0b")视为空白字符,而 java.util.regex 会。

还有一些未知的不兼容情况。如果用户无法容忍这种不兼容风险,请启用以下配置属性。

spark.gluten.sql.fallbackRegexpExpressions

FileSource 格式

目前,Gluten 完全支持 parquet 文件格式,部分支持 ORC。如果使用其他格式,scan 算子会回退到原生 Spark。

分区表扫描

Gluten 仅在文件路径中包含分区信息时才支持分区表扫描,否则会回退到原生 Spark。

不兼容行为

在某些情况下,Gluten 的结果可能与原生 Spark 不同。

JSON 函数

Velox 在 JSON 数据中只支持用双引号包裹字符串,不支持单引号。如果使用单引号,Gluten 会产生错误的结果。

在调用 get_json_object 函数时,Velox 不支持路径中的 [*],会返回 null。

Parquet 读取配置

Gluten 支持 spark.files.ignoreCorruptFiles,默认值为 false;即使将其设为 true,其行为也与设为 false 时相同。Gluten 会忽略 spark.sql.parquet.datetimeRebaseModeInRead,只返回 parquet 文件中写入的内容。它不考虑传统混合历(儒略-格里高利历)与前推格里高利历之间的差异,因此结果可能与原生 Spark 不同。

Parquet 写入配置

Spark 提供了 spark.sql.parquet.datetimeRebaseModeInWrite 配置,用于决定在写入 parquet 的日期/时间戳时使用传统混合历(儒略历 + 格里高利历)还是前推格里高利历。如果待读取的 parquet 文件是在该配置为 true 的情况下由 Spark 写入的,那么 Velox 的 TableScan 在读取该文件时会输出不同的结果。

分区写入

Gluten 支持静态分区写入和动态分区写入。

spark.sql("CREATE TABLE t (c int, d long, e long) STORED AS PARQUET partitioned by (c, d)")
spark.sql("INSERT OVERWRITE TABLE t partition(c=1, d) SELECT 2 as d, 3 as e")

Gluten 不支持分桶写入,将回退到原生 Spark。

spark.range(100).selectExpr("id as c1", "id % 7 as p")
  .write
  .format("parquet")
  .bucketBy(2, "c1")
  .save(f.getCanonicalPath)

CTAS 写入

Gluten 支持以 Parquet 文件格式执行 create table as select(CTAS)操作。

spark.range(100).toDF("id")
  .write
  .format("parquet")
  .saveAsTable("velox_ctas")

HiveFileFormat 写入

当输出文件类型为 parquet 时,Gluten 才支持 HiveFileFormat 的写入。

NaN 支持

Velox 不支持 NaN。因此在某些情况下可能得到非预期结果,例如将一个数字与 NaN 进行比较。

配置

Gluten 并不会遵循所有 parquet 配置。详情请参阅 docs/velox-parquet-write-configuration.md。

Spark 列式读取导致的致命错误

如果用户启用了 Spark 的列式读取,由于 Spark 的列式向量与 Gluten 的不兼容,可能会发生错误。

Spill(溢写)

在当前的 spill-to-disk(溢写到磁盘)功能实现中,当 shuffle 分区数设置得很大时,OutOfMemoryException 仍可能被触发。发生这种情况时,请尝试减少分区数以摆脱 OOM。

ParquetScan 中不支持的数据类型

  • Byte 类型会导致回退到原生 Spark

在 ColumnarShuffleExchange 中将 Map 类型用作哈希键

Spark 的 spark.sql.legacy.allowHashOnMapType 配置控制是否允许对 map 类型的键进行哈希。Gluten 在创建 ColumnarShuffleExchange 时会启用该配置,如](https://github.com/apache/gluten/blob/0dacac84d3bf3d2759a5dd7e0735147852d2845d/backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxSparkPlanExecApi.scala#L355-L363)所示。这样可以绕过 Spark 对未解析表达式的检查,从而在 ColumnarShuffleExchange 之前创建使用 hash(mapType) 运算符的 project。但是,如果在测试环境中禁用了 spark.sql.legacy.allowHashOnMapType,则使用 hash(mapType) 表达式的 project 在验证期间可能会抛出 Invalid call to dataType on unresolved object 异常,导致其回退到原生 Spark,如](https://github.com/apache/spark/blob/de5fa426e23b84fc3c2bddeabcd2e1eda515abd5/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/hash.scala#L291-L296)所示。启用该配置后,该 project 即可被下推到 Velox 执行。

评论

登录后参与评论

正在加载评论…