1.UDF和UDTF简介
UDF是User-Define-Function,一般是指一个输入一个输出,UDTF是UDF变种,可一个输入多个输出。UDAF是用户聚合,可以多行输入,一个输出。需要注意的是这些函数写好之后需要在平台或者脚本里配合sql使用。
1.1开发前注意事项
在编写代码时,UDF有两种具体实现,你可以继承import org.apache.hadoop.hive.ql.exec.UDF;
来实现UDF,也可以继承public class top extends GenericUDF
,第一个不支持复杂数据类型,比如Map,struct等。如果你想解析这些数据必须继承GenernicUDF实现
2.开发一个UDTF的全部流程
2.1配置pom文件的依赖
hive-exec,hadoop-common两个依赖即可
2.2编写业务代码的逻辑实现
2.2.1先写一个简单的UDF
package hive.udf;//必须要写包名。不然一会儿不好导入
import org.apache.hadoop.hive.ql.exec.UDF;//UDF虽然会被提示弃用了但是正常用就行
public class Twosum extends UDF {
public int evaluate(int input){
return input+233;
}
}
- 包名必须要写,不然hive里没办法把生成的jar包导进去
- 实现evalute方法即可,经过简单的处理直接return。
- 其实GenericUDF还有init方法用来初始化,该方法只执行一次,还有display方法用来报错。但是这些都可以不去实现。
2.2.2编写复杂的UDTF
该UDTF是TopN问题ETL部分
pom中依赖还是上面那两个
基本逻辑就是有个很长的字符串,里面是多个key:value的键值对,每一个键值对的分隔符是ETX(EndOfText)也就是ASCII的第三个控制字符(\u0003就是十六进制的3)。每个key和value分隔符是EOT(End Of Transmision)是第四个控制字符。
拆分的结果是每个键值对都被拆成key和value两列。
public class top extends GenericUDTF {
public static final Logger LOGGER = LogManager.getLogger(top.class);
@Override
public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
//定义输出数据的列名
List<String> filedNames = new ArrayList<String>();
List<ObjectInspector> fieldOIS = new ArrayList<ObjectInspector>();
filedNames.add("key");
fieldOIS.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
filedNames.add("value");
//定义输出数据的类型
fieldOIS.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(filedNames, fieldOIS);
}
@Override
public void process(Object[] objects) throws HiveException {
String input = objects[0].toString();
String[] datadsplit = input.split("\u0003");
for (String s : datadsplit) {
String[] result = s.split("\u0004");
forward(result);
}
}
@Override
public void close() throws HiveException {
}
}
- init方法必须实现,并且得用新的init方法,如果参数输成了老款或者没有实现init方法会报错
IllegalStateException Should not be called directly
- init方法中是用来定义输出信息的,需要注意的是filename add一次filedOIS也得add一次,如果输出多列数据的话。
- 如果处理完是数列或者数组,直接给forward函数即可。他会返回一行。
2.3配置工件及部署和使用
- 首先在IDEA左上角项目设置里找到工件,新建一个工件。选依赖辅助项目。然后再工具栏构建中找到构建工件。构建成功后再项目文件的out目录可以看见jar包
- 上传到hive的服务器,随便一个文件夹就可以,然后cd到该目录
- zip -d jar包 ‘META-INF/.SF’ ‘META-INF/.RSA’ ‘META-INF/*SF’
- 使用上述命令消除异常签名
- 再hive客户端或者datagrip上执行 add jar xxx.jar
- 继续create function twosum as ‘hive.udf.Twosum’;//这个as后面是包名+类名
- 接下来就可以调用了
- select twosum(name) from t_user;
3.TopN问题解法
上面的函数已经把所有的key:value拆分完毕,接下来做聚合和排序即可
create table topnend as
select types,sum(statusvalue) as value
from topnfinal
group by types;
select * from topnend
order by value desc ;