使用不可序列化的对象创建SparkSQL UDF

时间:2017-06-27 13:51:12

标签: scala apache-spark serialization hive udf

我正在尝试编写一个我想在sqlContext中的Hive表上使用的UDF。是否可以包含来自其他不可序列化的库的对象?这是一个不起作用的最小例子:

def myUDF(s: String) = {
 import sun.misc.BASE64Encoder
 val coder= new BASE64Encoder
 val encoded= decoder.encode(s)
 encoded
}

我在spark shell中注册函数为udf函数

val encoding = sqlContext.udf.register("encoder", myUDF)

如果我尝试在表“test”上运行它

sqlContext.sql("SELECT encoder(colname) from test").show()

我收到错误

org.apache.spark.SparkException: Task not serializable
object not serializable (class: sun.misc.BASE64Encoder, value: sun.misc.BASE64Encoder@4a7f9a94)

有解决方法吗?我尝试将myUDF嵌入到一个对象和一个类中但是也没有用。

1 个答案:

答案 0 :(得分:1)

您可以尝试将udf功能定义为

def encoder = udf((s: String) => {
  import sun.misc.BASE64Encoder
  val coder= new BASE64Encoder
  val encoded= coder.encode(s.getBytes("UTF-8"))
  encoded
})

udf函数调用为

dataframe.withColumn("encoded", encoder(col("id"))).show

<强>更新

正如@santon指出, dataframe 中的每个都会启动BASE64Encoder编码器,这可能会导致性能问题。解决方案是创建BASE64Encoder静态对象并在udf函数内调用它。