Hive是一种构建在Hadoop上的数据仓库,Hive把SQL查询转换为一系列在Hadoop集群中运行的MapReduce作业,是MapReduce更高层次的抽象,不用编写具体的MapReduce方法,带来了很多便利,但是有时候hive提供的函数功能满足不了业务需要,就需要我们自己来写UDF函数来辅助完成。UDF函数其实就是一个简单的函数,执行过程就是在Hive转换成Mapreduce程序后,执行java方法,类似于像Mapreduce执行过程中加入一个插件,方便扩展。UDF只能实现一进一出的操作,如果需要实现多进一出,则需要实现UDAF,而如果要一进多出则需要UDTF。
概述
开发自定义UDF函数有两种方式:
- 一个是继承
org.apache.hadoop.hive.ql.exec.UDF
; - 另一个是继承
org.apache.hadoop.hive.ql.udf.generic.GenericUDF
;
如果是针对简单的数据类型,比如String、Integer等可以使用UDF
,如果是针对复杂的数据类型,比如Array、Map、Struct等,可以使用GenericUDF
,另外,GenericUDF
还可以在函数开始之前和结束之后做一些初始化和关闭的处理操作。
UDF
如果继承UDF
,则我们只需要实现 public Object evaluate(Object args) {}
方法即可。由于 evaluate
并未在UDF
父类中具体说明,因此,用户实现的UDF
中,函数 evaluate
的返回类型和参数可以自己指定。当用户实现的UDF
在 Hive 中执行时,Hive将会执行函数 evaluate
中的内容,我们来看下Hive提供的hour
函数,是获取给定时间的小时信息,步骤如下:
- 首先根据给定日期的格式来获取日期Date;
- 通过Date初始化Calendar;
- 通过Calendar获取相应的小时信息。
// int hour(string date)
@Description(name = "hour",
value = "_FUNC_(date) - Returns the hour of date",
extended = "date is a string in the format of 'yyyy-MM-dd HH:mm:ss' or "
+ "'HH:mm:ss'.\n"
+ "Example:\n "
+ " > SELECT _FUNC_('2009-07-30 12:58:59') FROM src LIMIT 1;\n"
+ " 12\n"
+ " > SELECT _FUNC_('12:58:59') FROM src LIMIT 1;\n" + " 12")
@VectorizedExpressions({
VectorUDFHourLong.class, VectorUDFHourString.class})
public class UDFHour extends UDF {
private final SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final SimpleDateFormat formatter2 = new SimpleDateFormat("HH:mm:ss");
private final Calendar calendar = Calendar.getInstance();
private final IntWritable result = new IntWritable();
public UDFHour() {
}
/**
* Get the hour from a date string.
*
* @param dateString
* the dateString in the format of "yyyy-MM-dd HH:mm:ss" or
* "yyyy-MM-dd".
* @return an int from 0 to 23. null if the dateString is not a valid date
* string.
*/
public IntWritable evaluate(Text dateString) {
if (dateString == null) {
return null;
}
try {
Date date = null;
try {
date = formatter1.parse(dateString.toString());
} catch