文档目的
笔者在工作中有接触到 Hive UDF 的开发任务,大部分 UDF 开发并不困难,困难的往往是:
- 不清楚 UDF 代码的编写逻辑(UDF、UDTF、UDAF)
- 不清楚如何传入特定类型的参数
- 不清楚如何返回特定类型的结果
特此整理一番,供自己日后工作参考之用。同时也分享给大家,可以指导初学者开发自定义UDF,也可以作为随用随查的参考手册:
UDF概念
Hive 一共有三种 UDF:
- UDF
- UDTF
- UDAF
UDF(user-defined function)
普通函数,也是最常用的UDF类型
一行输入(可以传入多个参数),返回一个(一行一列)结果
比如字符串转小写函数:lower():
- 接收一个字符串参数
- 返回一个转小写后的字符串结果
hive> select lower('HELLO WORLD');
# 结果
hello world
复制代码
UDTF(user-defined table-generating function)
表生产函数
一行输入,输出多行结果
比如经常和 lateral view 语法一起搭配使用的explode()
explode():
- 接收一个数组参数
- 返回多行结果,每行一列,其数据为数组参数元素类型
hive> select explode(split('1,2,3', ','));
# 结果
1
2
3
复制代码
UDAF(user-defined aggregate function)
聚合函数
聚合多行数据,得到一行结果
我们经常用到的 sum()、count()、avg() 就是 UDAF,搭配 group by,将多行数据划分成多组然后进行聚合
-- 按年龄分组,统计每个年龄的用户人数
select age, count(1) as cc
from user_info
group by age
# 返回结果
age cc
18 11
19 22
20 33
复制代码
UDF开发步骤
第一步:编写代码
先判断函数的类型,是UDF、UDTF还是UDAF?
根据函数的类型,实现对应的类,并编写代码实现逻辑
代码开发请阅读:
第二步:打包并上传
将代码打包成jar,并将jar上传到Hive服务器
打包时,需要把依赖打入jar包,但不需要 hive-exec,在pom.xml中,将其 scope 设为 provided。因为Hive的lib目录下已经包括了 hive-exec 的jar,Hive 会自动将其加载
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>2.3.4</version>
<!-- 不需要打入jar包 -->
<scope>provided</scope>
</dependency>
</dependencies>
复制代码
第三步:注册临时函数
- 启动hive cli,将jar添加到本次会话中
hive> add jar <打包好的jar的全路径>;
复制代码
- 创建临时函数
hive> create temporary function <函数名> as 'UDF入口类全路径';
复制代码
Hive的函数分为临时函数和永久函数:
- 临时函数:只在当前客户端会话中生效的函数,不会影响到其他的会话。客户端退出后,临时函数就失效了
- 永久函数:注册永久函数后,其他的客户端会话也可以使用这个函数。客户端退出后,永久函数也不会失效
因为UDF开发完成后,需要进过一些测试才能确认代码是否没有问题。在测试UDF代码时,务必使用临时函数进行测试。这样即使代码出现了问题,也不会把函数真正的注册到Hive。代码测试完毕并且确认无误后,再将函数注册为永久函数
临时函数创建/删除语法
# 创建临时函数
CREATE TEMPORARY FUNCTION <函数名> AS <class全路径>;
# 删除临时函数
DROP TEMPORARY FUNCTION [IF EXISTS] <函数名>;
复制代码
永久函数创建/删除语法
# 创建永久函数
CREATE FUNCTION [db_name.]function_name AS class_name
[USING JAR|FILE|ARCHIVE 'file_uri' [, JAR|FILE|ARCHIVE 'file_uri'] ];
# 删除永久函数
DROP FUNCTION [IF EXISTS] function_name;
复制代码
关于Hive函数的创建和删除可以参考:官方文档
第四步:测试
这一步也没啥好说的,主要是测试刚刚创建的临时函数是否符合功能预期