我正在尝试编写一个我想在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嵌入到一个对象和一个类中但是也没有用。
答案 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
函数内调用它。