UDF、UDTF、UDAF区别详解

好的,UDF、UDTF 和 UDAF 是三种在大数据处理框架(如 Hive、Spark SQL、Flink SQL)中常见的用户自定义函数类型。它们的主要区别在于输入数据的行数、输出数据的行数以及处理逻辑

特性UDF (User-Defined Function)UDTF (User-Defined Table-Generating Function)UDAF (User-Defined Aggregation Function)
核心功能单行输入进行处理,返回单个值单行输入进行处理,返回多行多列的结果。多行输入(一个分组)进行处理,返回单个聚合值
输入一行数据中的一个或多个列值。一行数据中的一个或多个列值。多行数据(一个分组内的所有行)。
输出一个标量值 (Scalar Value)。一个表 (多行,每行可以有多个列)。一个聚合值 (Scalar Value)。
行为类比类似于编程语言中的普通函数。 f(a, b) -> c类似于一个能“炸开”输入并产生新行的函数。 f(a) -> (x, y), (p, q)类似于 SQL 中的 SUM(), COUNT(), AVG() 等聚合函数。 f([a1, a2, a3]) -> c
关键特点一对一 (1行输入 -> 1个输出)一对多 (1行输入 -> 多行输出)多对一 (多行输入 -> 1个输出)
主要用途数据清洗、转换、计算单个值。解析复杂结构(如JSON数组、Map)、行转列(Pivot)、数据展开(Explode)。分组统计、聚合计算(求和、平均、最大值、最小值、自定义聚合逻辑)。
Hive 示例SELECT my_udf(name) FROM users;SELECT my_udtf(json_array) AS item, price FROM logs;
(LATERAL VIEW 常一起使用)
SELECT department, my_udaf(salary) FROM employees GROUP BY department;
Spark 示例spark.udf.register("myUdf", (s: String) => s.toUpperCase)
df.select(myUdf($"name"))
通常实现为扩展 org.apache.spark.sql.api.java.UDF1 并返回 Iterable[Row] 或使用 flatMap实现 UserDefinedAggregateFunctionAggregator 抽象类/特质。
Flink 示例tableEnv.registerFunction("myUdf", new MyScalarFunction());
table.select("myUdf(myField)");
实现 TableFunction 接口。
table.joinLateral(call("myUdtf", $("myField")).as("newField1", "newField2"))
实现 AggregateFunction 接口。
table.groupBy($("key")).aggregate(call("myUdaf", $("value")).as("myResult")).select($("key"), $("myResult"));
通俗比喻给一个人(一行)量身高,输出一个数字(身高值)。打开一个人的背包(一行),把里面的每件物品(多行)都拿出来单独放好。统计一群人的平均身高(多行输入),输出一个平均身高值(一个结果)。

详细解释:

  1. UDF (User-Defined Function) - 用户定义函数

    • 作用: 最常见的自定义函数类型。它对输入的单个行进行操作,读取该行中一个或多个列的值,经过计算或处理后,返回一个单一的结果值
    • 输入/输出: 一行输入 -> 一个标量值输出。
    • 类比: 就像数学函数 y = f(x) 或者编程语言中的一个方法 String upperCase(String input)
    • 典型应用:
      • 字符串操作:转换大小写、拼接、替换、提取子串。
      • 数学计算:对数、指数、三角函数、自定义公式。
      • 数据类型转换:StringDateStringInteger
      • 条件逻辑:模拟 CASE WHEN 语句的复杂逻辑。
    • Hive 示例: SELECT toUpper(name), my_custom_calculation(salary, bonus) FROM employees;
    • Spark 示例: df.withColumn("full_name", concat_udf(col("first_name"), col("last_name")))
  2. UDTF (User-Defined Table-Generating Function) - 用户定义表生成函数

    • 作用: 它对输入的单个行进行操作,读取该行中一个或多个列的值,然后生成零行、一行或多行输出结果。输出的每行可以包含多个列。它“炸开”或“展开”了输入行。
    • 输入/输出: 一行输入 -> 零行、一行或多行输出(构成一个虚拟表)。
    • 关键特点: 必须与 LATERAL VIEW (在 Hive 中) 或 CROSS JOIN LATERAL TABLE(...) / JOIN LATERAL TABLE(...) (在标准 SQL/Spark/Flink 中) 结合使用,才能将 UDTF 产生的多行结果与原始表的其他列关联起来。
    • 典型应用:
      • 解析数组(ARRAY)或映射(MAP)类型的列:将数组中的每个元素或映射中的每个键值对拆分成单独的行。EXPLODE 是 Hive/Spark 内置的典型 UDTF。
      • 解析复杂结构:如 JSON 字符串、XML 字符串,将其内容解析成多行多列的结构化数据。
      • 行转列(Pivoting):虽然 UDTF 本身不是直接做透视表,但可以通过生成多行来辅助实现。
      • 数据生成:基于输入参数生成一系列值(如时间序列)。
    • Hive 示例:
      SELECT user_id, word
      FROM logs
      LATERAL VIEW explode(split(text, ' ')) words_table AS word; -- explode 是内置 UDTF
      
    • Spark 示例: (使用 explode)
      df.select($"user_id", explode($"hobbies").as("hobby"))
      
  3. UDAF (User-Defined Aggregation Function) - 用户定义聚合函数

    • 作用: 它对一组行(通常是一个 GROUP BY 分组或窗口内的所有行)进行操作。它接收该组内所有行中某个(或某些)列的值,执行聚合计算(如求和、计数、平均、最大值、最小值或任何自定义逻辑),并最终返回一个单一的聚合结果值
    • 输入/输出: 多行输入(一个分组) -> 一个标量值输出。
    • 实现复杂度: 通常是最复杂的一类 UDF,因为它需要管理聚合过程中的中间状态。实现时通常需要定义:
      • 一个用于存储中间聚合结果的数据结构(缓冲区)
      • 初始化缓冲区的方法 (initializecreateAccumulator)。
      • 更新缓冲区的方法 (iterateaccumulate),处理每一行输入。
      • 合并两个缓冲区的方法 (merge),用于分布式计算(如 MapReduce 或 Spark 的 shuffle 阶段)。
      • 最终计算并返回结果的方法 (terminategetValue)。
    • 典型应用:
      • 自定义统计指标:计算中位数、众数、分位数、方差、标准差、加权平均、复杂业务指标(如客户生命周期价值)。
      • 内置聚合函数的扩展或组合:实现标准 SQL 没有提供的聚合逻辑。
      • 复杂数据汇总。
    • Hive 示例: SELECT department, my_custom_avg(salary) FROM employees GROUP BY department;
    • Spark 示例: (实现 UserDefinedAggregateFunction 或更现代的 Aggregator)
      val myUdaf = new MyCustomAverageUdaf()
      df.groupBy($"department").agg(myUdaf($"salary").as("avg_salary"))
      

总结:

  • UDF逐行转换数据,输入一行,输出一个新的值。
  • UDTF展开或解析单行数据,输入一行,输出零到多行新数据(可能多列)。常与 LATERAL VIEW / JOIN LATERAL 联用。
  • UDAF跨多行聚合数据(分组或窗口),输入多行,输出一个汇总结果。用于 GROUP BY 或窗口函数中。

理解这三者的核心区别在于它们处理的数据粒度(单行 vs 多行)和输出的结构(单个值 vs 多行 vs 聚合值),是有效使用它们进行复杂数据处理的关键。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走过冬季

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值