Velox 后端的限制
本文通过列举一些已知情况来描述 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.fallbackRegexpExpressionsFileSource 格式
目前,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 执行。
评论
登录后参与评论
KnowForge