Hive自定义函数
文章目录
定义
当 Hive 提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。常用来自定义的是 UDF、UDTF 函数。聚合函数 UDAF 能够满足我们使用的基本都已经内置了。
根据用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function):一进一出
(2)UDAF(User-Defined Aggregation Function):聚集函数,多进一出(类似于:count/max/min)
(3)UDTF(User-Defined Table-Generating Functions):一进多出,如 lateral view explode()
官方文档地址
https://cwiki.apache.org/confluence/display/Hive/HivePlugins
自定义函数步骤
创建一个Maven工程,导入依赖
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
</exclusion>
</exclusions>
<version>3.1.2</version>
</dependency>
创建自定义函数类
自定义 UDF 函数,创建的类需继承 GenericUDF类,重写方法(org.apache.hadoop.hive.ql.udf.generic.GenericUDF)
自定义 UDTF 函数,创建的类需继承 GenericUDTF类,重写方法(org.apache.hadoop.hive.ql.udf.generic.GenericUDTF)
在 hive 的命令行窗口创建函数
创建函数分为:创建临时函数、创建永久函数 两种
创建函数命令如下:
create [temporary] function [dbname.]function_name AS class_name;
删除函数命令如下:
drop [temporary] function [if exists] [dbname.]function_name;
创建临时函数
1.将 maven 工程打包后的 jar,添加到 linux 服务器某个目录下
2.使用命令添加 jar,命令为:add jar 目录(jar所在linux目录)
3.创建function,命令:create temporary function 函数名 as 类路径(jar包中自定义函数的类路径)
4.通过命令:show functions可查看自己创建的函数。
5.提示:临时函数,在hive客户端关闭后失效,对 hive 中的全部数据库有效
创建永久函数
1.将 maven 工程打包后的 jar,上传到 hdfs 某个目录下(目录可自定义)
2.创建function,命令:create function ‘库名.函数名’ as ‘类路径’ using jar ‘jar包所在hdfs目录’
3.通过命令:show functions可查看自己创建的函数 (如果函数名不是【库名.函数名】格式,show functions是看不到的)。
4.提示:永久函数,只对当前所在库生效,其他库均不生效,所以建议使用【库名.函数名】命名方式。函数不会因为客户端的关闭而失效。
5.在 test 库下创建函数,名称为 test.split,在test 库下可直接 split() 方式使用。如需在 default 库下使用,则可通过加 test 前缀使用。
UDF
/**
* 自定义 UDF 函数,需要继承 GenericUDF 类
* 需求: 计算指定字符串的长度
*/
public class MyStringLength extends GenericUDF {
/**
*
* @param arguments 输入参数类型的鉴别器对象
* @return 返回值类型的鉴别器对象
* @throws UDFArgumentException
*/
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws
UDFArgumentException {
// 判断输入参数的个数
if(arguments.length !=1){
throw new UDFArgumentLengthException("Input Args Length
Error!!!");
}
// 判断输入参数的类型
if(!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)
){
throw new UDFArgumentTypeException(0,"Input Args Type
Error!!!");
}
//函数本身返回值为 int,需要返回 int 类型的鉴别器对象
return PrimitiveObjectInspectorFactory.javaIntObjectInspector;
}
/**
* 函数的逻辑处理
* @param arguments 输入的参数
* @return 返回值
* @throws HiveException
*/
@Override
public Object evaluate(DeferredObject[] arguments) throws
HiveException {
if(arguments[0].get() == null){
return 0;
}
return arguments[0].get().toString().length();
}
@Override
public String getDisplayString(String[] children) {
return "";
}
}
打成 jar 包上传到服务器/opt/soft/hive312/lib/目录下
将 jar 包添加到 hive 的 classpath
hive (default)> add jar /opt/soft/hive312/lib/hivestu-2.0.2.jar;
建临时函数与开发好的 java class 关联
hive (default)> create temporary function myudf as "com.nj.hive.MyStringLength";
即可在 hql 中使用自定义的函数
select ename,my_len(ename) ename_len from emp;
UDTF
/*
* UDTF解决输入一行,输出多行的需求
* 输入 "hello,world,liwei,bangbangtang",","
*
* */
public class MyUDTF extends GenericUDTF {
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
//输出数据类型说明
ArrayList<String> fieldNames = new ArrayList<>();
fieldNames.add("word");
List<ObjectInspector> fieldOIs =new ArrayList<>();
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs);
}
private List<String> wordList =new ArrayList<>();
@Override
public void process(Object[] args) throws HiveException {
//输入 “hello,world,liwei,bangbangtang”
String data=args[0].toString();
String splitkey = args[1].toString();
String[] words = data.split(splitkey);
for (String word:
words) {
wordList.clear();
wordList.add(word);
forward(wordList);
}
}
@Override
public void close() throws HiveException {
}
}
后续步骤同上