用户自定义函数(UDF)是一种允许用户在 Spark SQL 中定义自己的函数并应用于 DataFrame 的功能。UDF 可以接受一个或多个输入参数,并生成一个输出结果。UDF 的目的是扩展 Spark SQL 的功能,使用户能够使用自定义逻辑对数据进行处理和转换。
在 Apache Spark 中,UDF 的原理是通过创建 UserDefinedFunction
对象来表示用户定义的函数,并将其应用于 DataFrame 的列。UserDefinedFunction
类封装了用户定义的函数对象、返回值类型和输入参数类型等信息。它提供了方法来配置 UDF 的属性,例如是否可空、是否确定性等。通过调用 apply
方法,可以将 UserDefinedFunction
应用到 DataFrame 的列上,从而得到一个新的 Column 对象,该对象包含了应用 UDF 后的结果。
普通定义的函数
def functionName(parameter1: Type1, parameter2: Type2): ReturnType = {
// 函数体
// 最后一行表达式的值将作为返回值
}
- 普通定义的函数:只能在DataFrame API中使用,不能直接在SQL查询中使用。
- 普通定义的函数:在DataFrame API中使用时,Spark的Catalyst优化器可以对其进行优化。
- 普通定义的函数:在DataFrame API中使用时,类型检查在编译时进行。
使用udf对象创建的函数
一旦你注册了自定义函数,你就可以在SQL查询中像使用内置函数一样使用它。
- 使用
udf
对象注册的函数:可以注册为UDF,并在SQL查询中使用。- 使用
udf
对象注册的函数:在SQL查询中使用时,UDF不能被Catalyst优化器优化,因此性能可能较差。- 使用
udf
对象注册的函数:在SQL查询中使用时,类型检查在运行时进行,因此更容易出现类型错误。
注意导入
import org.apache.spark.sql.functions.udf
1.直接在udf中定义
val myUDFDirect = udf((input: String) => input.toUpperCase)
2.将函数注册为 UDF
// 方法 1:定义普通函数
def myFunction(input: String): String = {
// 你的逻辑在这里
input.toUpperCase
}
spark.udf.register("my_udf", myFunction _)
3.register
val dpdf = new SimpleDateFormat("yyyy-MM-dd")
val timeCover: UserDefinedFunction = spark.udf.register("timeCover", (event_time: String) => {
if (StringUtils.isEmpty(event_time)) {
0
}
else {
dpdf.parse(event_time).getTime
}
})
spark.udf.register("my_udf", myFunction _)
总结
使用udf
对象注册的函数和普通定义的函数各有优缺点。如果你需要在SQL查询中使用自定义逻辑,那么使用udf
对象注册的函数是必要的。然而,如果你主要在DataFrame API中工作,并且希望利用Spark的优化功能,那么普通定义的函数可能更合适。