Hive--自定义函数

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;
	}
}

打成helloudf.jar,并传到hive客户端的/home/hadoop目录下

在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;
		}

	}

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值