博客 HIve函数自定义UDF函数

HIve函数自定义UDF函数

   数栈君   发表于 2024-01-23 10:38  459  0

一、UDF概述
UDF全称:User-Defined Functions,即用户自定义函数,在Hive SQL编译成MapReduce任务时,执行java方法,类似于像MapReduce执行过程中加入一个插件,方便扩展。

二、UDF种类
UDF:操作单个数据行,产生单个数据行;
UDAF:操作多个数据行,产生一个数据行;
UDTF:操作一个数据行,产生多个数据行一个表作为输出;

三、如何自定义UDF
1.编写UDF函数,UDF需要继承org.apache.hadoop.hive.ql.exec.UDF,UDTF继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,UDAF使用比较少,这里先不讲解
2.将写好的类打包为jar,如HiveUDF-1.0.jar,并且上传到Hive机器或者HDFS目录
3.入到Hive shell环境中,输入命令add jar /home/hadoop/HiveUDF-1.0.jar注册该jar文件;或者把HiveUDF-1.0.jar上传到hdfs,hadoop fs -put HiveUDF-1.0.jar /home/hadoop/HiveUDF-1.0.jar,再输入命令add jar hdfs://hadoop60:8020/home/hadoop/HiveUDF-1.0.jar;
4.为UDF类起一个别名,create temporary function myudf as ‘com.master.HiveUDF.MyUDF’;注意,这里UDF只是为这个Hive会话临时定义的;
5.在select中使用myudf();

四、自定义实现UDF和UDTF
4.1 需求
1)UDF,自定义一个函数,并且实现把列中的数据由小写转换成大写
2)UDTF,拆分一个表中的name字段,以|为分割,分成不同的列,如下所示:

表中的数据为:

id name

1 Ba|qz
2 xa
1
2
3
4
要拆分成如下格式:

id name

1 Ba
1 qz
2 xa
1
2
3
4
5
4.2 项目pom文件
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.1.1</version>
</dependency>
1
2
3
4
5
4.3 Hive建表测试及数据
create table if not exists t_user (
id int,
name string
)
clustered by (id) into 2 buckets
row format delimited fields terminated by '|'
stored as orc TBLPROPERTIES('transactional'='true');
1
2
3
4
5
6
7
向Hive表中插入数据:

insert into t_user values(1,'Ba|qz');
insert into t_user values(1,'xa');
1
2
4.4 UDF函数编写
UDF函数需要继承org.apache.hadoop.hive.ql.exec.UDF类,并且添加evaluate方法,原因是:UDF类默认的UDFMethodResolver是org.apache.hadoop.hive.ql.exec.DefaultUDFMethodResolver,evaluate方法是在DefaultUDFMethodResolver中进行配置,默认绑定的是evaluate方法。

添加evaluate有两个注意事项:

1)evaluate方法遵循重载的原则,参数是用户自定义的,调用那个方法调用是在使用函数时候的参数决定。
2)evaluate方法必须有返回值,返回类型以及方法参数可以是Java数据或相应的Writable类。
1
2
具体实现:

public class MyUDF extends UDF {
public String evaluate(String s) {
if (s == null) {
return "";
}
return s.toUpperCase();
}
}
1
2
3
4
5
6
7
8
4.5 UDTF函数编写
1)UDTF限制(----后面为原文解析),官网地址:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-Built-inTable-GeneratingFunctions(UDTF)

在UDTF中Select里面不能有其他语句----No other expressions are allowed in SELECT/SELECT pageid, explode(adid_list) AS myCol… is not supported

UDTF不能被嵌套----UDTF’s can’t be nested/SELECT explode(explode(adid_list)) AS myCol… is not supported

UDTF不支持GROUP BY / CLUSTER BY / DISTRIBUTE BY / SORT BY----GROUP BY/ CLUSTER BY/ DISTRIBUTE BY/ SORT BY is not supported/SELECT explode(adid_list) AS myCol … GROUP BY myCol is not supported

继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,实现initialize,process,close三个方法。

2)注意事项

initialize方法制定了返回的列名及数据类型(forward写入数据的类型是一个数组,对应着initialize定义的列名),可以返回多个,在List里面对应即可。函数列名调用的时侯通过:myudtf(col,col1) t1 as co1,col2来使用列名。

3)实现

import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

public class MyUDTF extends GenericUDTF {

@Override
public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {

List<String> fieldNames = new ArrayList<>();
List<ObjectInspector> fieldTypes = new ArrayList<>();

fieldNames.add("col");
fieldTypes.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldTypes);
}

@Override
public void process(Object[] args) throws HiveException {

String col = args[0].toString();

String[] cols = col.split("\\|");
for (String c : cols) {
String[] results = new String[1];
results[0] = c;
forward(results);
}
}

@Override
public void close() throws HiveException {

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
4)在Hive Shell中添加临时函数

上传到Linux目录,然后用add jar来添加路径

hive>add jar /home/hadoop/hivetest/HiveUDF-1.0.jar
1
创建临时函数:

hive>create temporary function myudf as "com.master.HiveUDF.MyUDF";
hive>create temporary function myudtf as "com.master.HiveUDF.MyUDTF"
1
2
5)UDF使用
1
select myudf(name) from t_user;
1
效果如下


4.6 UDTF使用
select myudtf(name) from t_user
1
效果如下:

但是貌似没有和前面的数据结合,这时候,需要用lateral view来操作,语句如下

select t1.id,t2.col from t_user t1 lateral view myudtf(name) t2 as col
1


lateral view用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/miaoge_miaoge/article/details/121888184



《数据治理行业实践白皮书》下载地址:https://fs80.cn/4w2atu

《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack  
0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群