总结
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 这是最精华的图,请多次理解,并且结合代码推导过程。