本篇文章详细讲解UDF、UDAF、UDTF的使用及注意事项,下章将会讲解在UDF的基础之上使用Hive 2.1中transform接口。
其次我的个人网站也开始投入使用了,多多支持:http://amazingwu.xyz
Hive进行UDF开发十分简单,此处所说UDF为Temporary的function,所以需要hive版本在0.4.0以上才可以。
一、背景:
Hive是基于Hadoop中的MapReduce,提供HQL查询的数据仓库。Hive是一个很开放的系统,很多内容都支持用户定制,包括:
a)文件格式:Text File,Sequence File
b)内存中的数据格式: Java Integer/String, Hadoop IntWritable/Text
c)用户提供的 map/reduce 脚本:不管什么语言,利用 stdin/stdout 传输数据
d)用户自定义函数: Substr, Trim, 1 – 1
e)用户自定义聚合函数: Sum, Average…… n – 1
二、用法
UDF
定义:UDF(User-Defined-Function),用户自定义函数对数据进行处理。
UDF函数可以直接应用于select语句,对查询结构做格式化处理后,再输出内容。
Hive的UDF根据继承的父类可以分为UDF类(指类别,旧)和GenericUDF类,新版本的Hive陆续把部分UDF类的UDF,改写成了GenericUDF类的UDF。实现自己的Hive的UDF,一种是直接继承Hive中的org.apache.hadoop.hive.ql.UDF,另一种是继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF。
1.第一种方法使用UDF函数的时候需要注意一下几点:
a)自定义UDF需要继承org.apache.hadoop.hive.ql.UDF。
b)需要实现evaluate函。
c)evaluate函数支持重载。
以下是两个数求和函数的UDF。evaluate函数代表两个整型数据相加,两个浮点型数据相加,可变长数据相加,Hive的UDF开发只需要重构UDF类的evaluate函数即可。例:
import org.apache.hadoop.hive.ql.exec.UDF;
public final class Add extends UDF {
public Integer evaluate(Integer a, Integer b) {
if (null == a || null == b) {
return null;
} return a + b;
}
public Double evaluate(Double a, Double b) {
if (a == null || b == null)
return null;
return a + b;
}
public Integer evaluate(Integer... a) {
int total = 0;
for (int i = 0; i < a.length; i++)
if (a[i] != null)
total += a[i];
return total;
}
}
2.GenericUDF相比较于UDF,具有更加丰富的功能,一个是可以接受和返回复杂数据类型了,例如Array什么的结构体类型,而不像UDF类那样只能是int、string之类的基本类型(当然真正代码中定义的是包装过的后缀为Writable的类型,但还是表示基本类型);新的改进可以接受可变长度以及无限长度的参数了,因为可以用数组来表示输入参数了,而不需要像UDF类的实现类那样,要几种参数组合,就得重载几种方法;最重要的改进是可以通过DeferredObject类来实现所谓的”short-circuit“优化。数组的方式传递进参数,将会给用户开发自己的UDF提供极大的便捷性。不足的是GenericUDF的输出只能有一列,当然这个功能可以通过UDTF来弥补。
下面给出一个例子讲解下GenericUDF的使用:
我将通过建立一个UDF函数:containsString,来加深对该API了解,该函数接收两个参数:
一个String的列表(list)
一个String
根据该list中是否包含所提供的string来返回true或者false,如下:
containsString(List(“a”, “b”, “c”), “b”); // true
containsString(List(“a”, “b”, “c”), “d”); // false
class ComplexUDFExample extends GenericUDF {
ListObjectInspector listOI;
StringObjectInspector elementOI;
@Override
public String getDisplayString(String[] arg0) {
return "arrayContainsExample()"; // this should probably be better
}
&