首页 > 解决方案 > Spark else() 总是被评估

问题描述

想象一下我有以下代码:

val option: Option[String] = ??? // May be some or none
val validation: Boolean = ??? // May be true or false

val df = ??? // load data

现在我想添加两个新列:

option = None 我想在和时抛出异常validation = false。但是,当验证为真且默认选项为无时,我会抛出异常。就像 else 函数总是为每一行执行一样,无论 when 子句中的条件如何。

谢谢。

标签: apache-sparkapache-spark-sql

解决方案


您混淆了两件不同的事情——执行计划的评估(这就是这里发生的事情)和对实际数据的物理计划的评估(这里没有发生)。必须始终评估执行计划,否则 Spark 将不知道如何生成相应的代码。另一方面,不同的评估分支可以从计划中删除或在执行期间跳过(使用标准控制流)。

在您的情况下,计划根本无效,因为None不能用作文字。这并不意味着在实际数据上评估此类计划的任何方式(实际上可能会或可能不会短路,具体取决于所使用的表达式)。

实际上,您可以轻松地检查CASE WHEN在这种简单的情况下,针对琐碎真或假的优化计划是否完全删除了其他分支

spark.range(1).select(when(lit(true), 1).otherwise(2) as "x").explain(true)
== Parsed Logical Plan ==
Project [CASE WHEN true THEN 1 ELSE 2 END AS x#10]
+- Range (0, 1, step=1, splits=Some(8))

== Analyzed Logical Plan ==
x: int
Project [CASE WHEN true THEN 1 ELSE 2 END AS x#10]
+- Range (0, 1, step=1, splits=Some(8))

== Optimized Logical Plan ==
Project [1 AS x#10]
+- Range (0, 1, step=1, splits=Some(8))

== Physical Plan ==
*(1) Project [1 AS x#10]
+- *(1) Range (0, 1, step=1, splits=8)
spark.range(1).select(when(lit(false), 1).otherwise(2) as "x").explain(true)
== Parsed Logical Plan ==
Project [CASE WHEN false THEN 1 ELSE 2 END AS x#14]
+- Range (0, 1, step=1, splits=Some(8))

== Analyzed Logical Plan ==
x: int
Project [CASE WHEN false THEN 1 ELSE 2 END AS x#14]
+- Range (0, 1, step=1, splits=Some(8))

== Optimized Logical Plan ==
Project [2 AS x#14]
+- Range (0, 1, step=1, splits=Some(8))

== Physical Plan ==
*(1) Project [2 AS x#14]
+- *(1) Range (0, 1, step=1, splits=8)

但是,您不应该对此进行推断 - 某些执行模式(特别是 UDF 的某些变体)无法通过这种方式进行优化。

详情请参阅SimplifyConditionals来源


推荐阅读