执行 UDF 失败

Posted

技术标签:

【中文标题】执行 UDF 失败【英文标题】:Failed to execute UDF 【发布时间】:2020-12-24 15:49:51 【问题描述】:

存在字段“A”包含sql查询的表。有必要添加一个附加字段“B”,该字段将包含从“A”字段执行查询所花费的时间。我写了一个 UDF,一切正常,但是在缓存结果表或尝试将最终数据帧写入物理表时,出现错误:

"执行用户定义函数失败 ($anonfun$1: (string) => 字符串)"

。可能是什么问题呢? 示例:

val set_time = udf((query: String) => 
val start = new Timestamp(new Date().getDate)
val count = spark.sql(s"$query").count
val time_query = (new Timestamp(new Date().getTime)).getTime() - start.getTime()
time_query.toString
)

源表“源”:

+--------------------+
|          A         |
+--------------------+
|"Select * From ..." |
|"Select * From ..." |
|"Select * From ..." |
|"Select * From ..." |
|"Select * From ..." |
+--------------------+
val result = spark.sql("from source").
withColumn("B", set_time(col("A")))

result.show
+--------------------+------+
|          A         |   B  |
+--------------------+------+
|"Select * From ..." | 356  |
|"Select * From ..." | 642  |
|"Select * From ..." | 2745 |
|"Select * From ..." | 1324 |
|"Select * From ..." | 635  |
+--------------------+------+

但是:

//ERROR
result.write.mode("overwrite").saveAsTable("dbName.result")

//ERROR
val result_cache = result.persist
result_cache.show

【问题讨论】:

【参考方案1】:

这里的问题是 UDF 在 spark 会话不可用的执行程序上工作。所以我猜你在"val count = spark.sql..." 行上得到了 NullPointer 异常。

您应该在不使用 UDF 而仅使用 function1 的驱动程序上执行此操作。同样使用 collect() 我想主表不大,可以放入驱动程序内存中:

例子:

import java.util.Date
import java.time.LocalDateTime

val set_time = (query: String) => 
val start = new Timestamp(new Date().getTime)
val count = spark.sql(s"$query").count
val time_query = (new Timestamp(new Date().getTime)).getTime() - start.getTime()
time_query.toString


val result = spark.sql("select 'select 1' as A union all select 'select 2' as A")
val s = result.collect().map(x =>(x(0).asInstanceOf[String],set_time(x(0).asInstanceOf[String]))).toList.toDF("A","B")

s.show 
s.cache().show 
+--------+---+
|       A|  B|
+--------+---+
|select 1|171|
|select 2|135|
+--------+---+

PS:你的例子中的val start = new Timestamp(new Date().getDate)也应该是val start = new Timestamp(new Date().getTime)

【讨论】:

以上是关于执行 UDF 失败的主要内容,如果未能解决你的问题,请参考以下文章

PIG UDF 加载 .gz 文件失败

Apache Spark Python UDF 失败

HIVE:UDF 错误失败:找不到类 <ClassName>

Pyspark udf 对于没有参数的函数失败,但适用于没有参数的 lambda

Java中的Hive UDF在创建表时失败

UDF 内存泄漏的解决方法