http://www.cnblogs.com/end/archive/2012/06/18/2553682.html
6 自定义函数
1. UDF
UDF(user defined function),即用户自定义函数,接受单行输入,并产生单行输出。
步骤如下:
1)自定义一个Java类并继承org.apache.hadoop.hive.ql.exec.UDF类
2)重写evaluate方法
下面来做一个演示:
编写java类:
package com.wv.hive.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
public class HelloUDF extends UDF {
public String evaluate(String str) {
return "helloUDF" + str;
}
}
在hive cli中添加jar,并创建模板函数:
hive (default)> add jar /home/hadoop/helloudf.jar;
Added [/home/hadoop/helloudf.jar] to class path
Added resources: [/home/hadoop/helloudf.jar]
hive (default)> create temporary function helloudf as 'com.wv.hive.udf.HelloUDF';
OK
Time taken: 0.013 seconds
验证该函数是否可以使用:
hive (default)> select helloudf(t.name) from test t;
OK
helloUDFwang
helloUDFliu
helloUDFzhao
Time taken: 0.12 seconds, Fetched: 3 row(s)
使用完helloudf函数后,可以使用如下命令来删除:drop temporary function helloudf;
2. UDAF
UDAF(user defined aggregation function),即用户自定义聚合函数,接受多行输入,并产生单行输出。比如MAX,COUNT函数。
1)编写resolver类,resolver类负责类型检查,操作符重载。
继承抽象类org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver,或者实现接口org.apache.hadoop.hive.ql.udf.GenericUDAFResolver2
2)编写evaluator类,evaluator真正实现UDAF的逻辑。
继承org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator。
在GenericUDAFEvaluator类中有一个内部枚举类:Mode,它表示了UDAF在mapreduce的各个阶段,理解Mode的含义,就可以理解hive的UDAF的运行流程。
public static enum Mode {
/**
* PARTIAL1: 这个是mapreduce的map阶段:从原始数据到部分数据聚合
* 将会调用iterate()和terminatePartial()
*/
PARTIAL1,
/**
* PARTIAL2: 这个是mapreduce的map端的Combiner阶段,负责在map端合并map的数据::从部分数据聚合到部分数据聚合:
* 将会调用merge() 和 terminatePartial()
*/
PARTIAL2,
/**
* FINAL: mapreduce的reduce阶段:从部分数据的聚合到完全聚合
* 将会调用merge()和terminate()
*/
FINAL,
/**
* COMPLETE: 如果出现了这个阶段,表示mapreduce只有map,没有reduce,所以map端就直接出结果了:从原始数据直接到完全聚合
* 将会调用 iterate()和terminate()
*/
COMPLETE
};
编写一个实例:
package com.wv.hive.udaf;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.io.LongWritable;
public class CountBigThan extends AbstractGenericUDAFResolver {
// 参数类型检查
@Override
public GenericUDAFEvaluator getEvaluator(TypeInfo[] info)
throws SemanticException {
if (info.length != 2) {
throw new UDFArgumentTypeException(info.length - 1,
"Exactly two argument is expected.");
}
// 返回自定义的逻辑处理类
return new GenericUDAFCountBigThanEvaluator();
}
// 自定义的逻辑处理类
public static class GenericUDAFCountBigThanEvaluator extends
GenericUDAFEvaluator {
private LongWritable result;// 保存最终结果
private PrimitiveObjectInspector inputIO1;
private PrimitiveObjectInspector inputIO2;
/*
* map和reduce阶段都会执行init方法
* map阶段:parameter长度与udaf输入的参数个数有关
* reduce阶段:parameter长度为1
*/
@Override
public ObjectInspector init(Mode m, ObjectInspector[] parameters)
throws HiveException {
super.init(m, parameters);
// 最终结果
result = new LongWritable(0);
inputIO1 = (PrimitiveObjectInspector) parameters[0];
if (parameters.length > 1) {
inputIO2 = (PrimitiveObjectInspector) parameters[1];
}
return PrimitiveObjectInspectorFactory.writableLongObjectInspector;
}
@Override
// map阶段执行
public void iterate(AggregationBuffer agg, Object[] parameters)
throws HiveException {
assert (parameters.length == 2);
if (parameters == null || parameters[0] == null
|| parameters[1] == null) {
return;
}
double base = PrimitiveObjectInspectorUtils.getDouble(
parameters[0], inputIO1);
double tmp = PrimitiveObjectInspectorUtils.getDouble(parameters[0],
inputIO2);
if (base > tmp) {
((CountAgg) agg).count++;
}
}
@Override
// 保存一些聚合缓存结果
public AggregationBuffer getNewAggregationBuffer() throws HiveException {
CountAgg countAgg = new CountAgg();
reset(countAgg);
return countAgg;
}
public static class CountAgg implements AggregationBuffer {
long count;
}
@Override
public void reset(AggregationBuffer countAgg) throws HiveException {
CountAgg agg = (CountAgg) countAgg;
agg.count = 0;
}
@Override
public Object terminatePartial(AggregationBuffer agg)
throws HiveException {
// 将result值设为CountAgg.cout
result.set(((CountAgg) agg).count);
// 返回result
return result;
}
@Override
public void merge(AggregationBuffer agg, Object partial)
throws HiveException {
//将从terminatePartial方法返回的结果和缓存区中的结果相加
if (partial != null) {
long p = PrimitiveObjectInspectorUtils.getLong(partial,
inputIO1);
((CountAgg) agg).count += p;
}
}
@Override
public Object terminate(AggregationBuffer agg) throws HiveException {
// 将result值设为CountAgg.cout
result.set(((CountAgg) agg).count);
// 返回result
return result;
}
}
}