hive UDAF详解

User Defined Aggregation Funcation
用户自定义聚类方法,和group by联合使用
接受多个输入数据行,并产生一个输出数据行
(顺带一句,UDTF (user-defined table-generating function)
用户定义表生成函数,操作作用于单个数据行,且产生多个数据行)

两种实现

hive有两种UDAF:简单和通用
简单,利用抽象类UDAF和UDAFEvaluator,使用Java反射导致性能损失,且有些特性不能使用,如可变长度参数列表
通用,利用接口GenericUDAFResolver2(或者抽象类AbstractGenericUDAFResolver)和抽象类GenericUDAFEvaluator,可以使用​​所有功能,但比较复杂,不直观

简单方式实现

UDAF的运行流程

PARTIAL1:原始数据到部分聚合,调用iterate和terminatePartial –> map阶段
PARTIAL2: 部分聚合到部分聚合,调用merge和terminatePartial –> combine阶段
FINAL: 部分聚合到完全聚合,调用merge和terminate –> reduce阶段
COMPLETE: 从原始数据直接到完全聚合 –> map阶段,并且没有reduce

实现

需要继承org.apache.hadoop.hive.ql.exec.UDAF类
内部类Evaluator实现org.apache.hadoop.hive.ql.exec.UDAFEvaluator接口,主要实现init、iterate、terminatePartial、merge、terminate这几个方法

init

实例化Evaluator类的时候调用的,在不同的阶段需要返回不同的OI。其入参和返回值,以及Mode阶段的关系如下
阶段 入参 返回值的使用者
P1 原始数据 terminatePartial
P2 部分聚合数据 terminatePartial
F 部分聚合数据 terminate
C 原始数据 terminate

iterate

处理一行数据,接收传入的参数,并进行内部的轮转。其返回类型为boolean。

terminatePartial

无参数,类似于hadoop的Combiner,其为iterate函数轮转结束后,返回部分聚合数据的持久化对象。因为调用这个方法时,说明已经是map或者combine的结束了,必须将数据持久化以后交给reduce进行处理。只支持JAVA原始数据类型及其封装类型、HADOOP Writable类型、List、Map,不能返回自定义的类,即使实现了Serializable也不行,否则会出现问题或者错误的结果。

merge

接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean。

terminate

返回最终的聚集函数结果
getNewAggregationBuffer: 获取存放中间结果的对象

通用方式实现

两个步骤,第一个是编写resolver类,第二个是编写evaluator类。resolver负责类型检查,操作符重载。evaluator真正实现UDAF的逻辑
resolver通常继承org.apache.hadoop.hive.ql.udf.GenericUDAFResolver2,但是我们更建议继承AbstractGenericUDAFResolver,隔离将来hive接口的变化
GenericUDAFResolver和GenericUDAFResolver2接口的区别是,后面的允许evaluator实现可以访问更多的信息,例如DISTINCT限定符,通配符FUNCTION(*)
所有evaluators必须继承抽象类org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator。子类必须实现它的一些抽象方法,实现UDAF的逻辑。
GenericUDAFEvaluator有一个嵌套类Mode,这个类很重要,它表示了udaf在mapreduce的各个阶段
参考
http://www.tuicool.com/articles/6rEJBfm
http://www.cnblogs.com/ggjucheng/archive/2013/02/01/2888051.html

你可能感兴趣的:(hadoop,hive)