总结
hive的比较难的部分应该就是GenericUDAF,看了两天终于看明白了,有些点是我自己遇到卡住的点,记录下来希望对大家有所帮助。
一开始看的是《Hive 编程指南》中关于GenericUDAF的章节,例子有点难了。讲的是group_concat的实现。查了资料后觉得网上写的博客非常好,例子比较简单,更能够明白到底在说什么。
一定要结合MapReduce的过程来看,才会想明白。
不要偷懒,要将文章中的代码下载下来,具体查看他所继承的类,才能更快速理解内容。
参看
Hive UDAF开发详解
这一篇是最值得参考的文章,这里使用是统计字数的例子,比较简洁。
关于ObjectInspector
想要理解GenericUDAF一定要理解ObjectInspector,这是贯彻在其中的一个概念。这里也说了一篇博文,一定要参考。Hive中ObjectInspector的作用。
ObjectInspector在我看来是什么?其实就是类型检查和通过这个类能得到值,并且帮助它序列化和反序列化,达到数据流转无障碍的目的。
上图这些过程之间流转都是通过ObjectInspector达到数据流转的, 要知道这些过程中不乏有着跨节点的操作。
Model
这是一定要理解的,Model是什么? 其实Model就是决定了在Map阶段和Reduce阶段 在涉及到对列进行UDF函数计算的时候,会调用UDF类中的哪些方法,都是由Model值决定的。并不是所有的方法都会调用,只会调用有限的几个。再由上面的提到的ObjectInspector进行数据的流转。
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
};
这个类就是用来类型检查的。
public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters)
这是我非常想说的类,init()他会根据model值的不同来决定输入的类型和输出的类型,非常的灵活。并且注意,init()的调用不是单次的,是多次的。
// 确定各个阶段输入输出参数的数据格式ObjectInspectors
public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException;
注意这里的迭代,当map阶段从表中读取一行时,就会调用一次iterate()方法,如果存在多行,就会调用多次。
// map阶段,迭代处理输入sql传过来的列数据
public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException;、
1 这是最精华的图,请多次理解,并且结合代码推导过程。