为什么使用UDF查询失败"任务不可序列化"例外?

时间:2017-12-28 08:16:38

标签: scala apache-spark serialization apache-spark-sql

我创建了一个UDF,并且我试图将它应用于连接中的coalesce结果。 理想情况下,我想在加入期间这样做:

def foo(value: Double): Double = {
    value / 100
}

val foo = udf(foo _)

df.join(.....)
  .withColumn("value",foo(coalesce(new Column("valueA"), new Column("valueB"))))

但我得到例外Task not serializable。 有办法解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

使用lambda函数使其可序列化。这个例子工作正常。

    import org.apache.spark.sql.functions.col
import org.apache.spark.sql.functions.coalesce
import org.apache.spark.sql.functions.udf
val central: DataFrame = Seq(
  (1,  Some(2014)),
  (2,  null)
).toDF("key", "year1")

val other1: DataFrame = Seq(
  (1,  2016),
  (2,  2015)
).toDF("key", "year2")
def fooUDF = udf{v: Double => v/100}

val result = central.join(other1, Seq("key"))
  .withColumn("value",fooUDF(coalesce(col("year1"), col("year2"))))

答案 1 :(得分:0)

  

但我得到例外Task not serializable

臭名昭着的“Task not serializable”异常的原因是def foo(value: Double): Double是一个不可序列化的拥有对象的一部分(可能与SparkSession间接引用了一个不可序列化的SparkContext)。 / p>

解决方案是将方法定义为“独立”对象的一部分,该对象不引用不可序列化的值。

  

有办法解决这个问题吗?

请参阅@firas的other answer