Hive 简单UDAF开发(extends UDAF)

Hive UDAFUser- Defined Aggregation Funcation)用户自定义聚合函数是一个很好的功能,集成了先进的数据处理。Hive有两种UDAF:简单和通用。顾名思义,简单的UDAF,写的相当简单的,但因为使用Java反射导致性能损失,而且有些特性不能使用,如可变长度参数列表。通用UDAF可以使用​​所有功能,但是UDAF就写的比较复杂,不直观。

1、一下两个包是必须的import org.apache.hadoop.hive.ql.exec.UDAF org.apache.hadoop.hive.ql.exec.UDAFEvaluator

2、函数类需要继承UDAF类,内部类EvaluatorUDAFEvaluator接口。

3Evaluator需要实现 inititerateterminatePartialmergeterminate这几个函数。

ainit函数实现接口UDAFEvaluatorinit函数。

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

cterminatePartial无参数,其为iterate函数轮转结束后,返回轮转数据,terminatePartial类似于hadoopCombiner

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

e terminate 返回最终的聚集函数结果。

代码示例,用于计算商户星级的平均价格的UDAF

[java] view plain copy
  1. package com.dianping.credit.udaf.avgprice;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.hadoop.hive.ql.exec.UDAF;  
  7. import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;  
  8.   
  9. /** 
  10.  * 计算商户的平均价格 
  11.  * @author xinchun.wang 
  12.  * 
  13.  */  
  14. public final class AvgPriceUDAF extends UDAF {  
  15.   
  16.     /** 
  17.      * The internal state of an aggregation for average. 
  18.      *  
  19.      * Note that this is only needed if the internal state cannot be represented 
  20.      * by a primitive. 
  21.      *  
  22.      * The internal state can also contains fields with types like 
  23.      * ArrayList<String> and HashMap<String,Double> if needed. 初始化点评的平均价格列表 
  24.      */  
  25.     public static class UDAFAvgPriceState {  
  26.         private List<Integer> oldPriceList = new ArrayList<Integer>();  
  27.         private List<Integer> newPriceList = new ArrayList<Integer>();  
  28.   
  29.     }  
  30.   
  31.     /** 
  32.      * The actual class for doing the aggregation. Hive will automatically look 
  33.      * for all internal classes of the UDAF that implements UDAFEvaluator. 
  34.      */  
  35.     public static class UDAFAvgPriceEvaluator implements UDAFEvaluator {  
  36.   
  37.         UDAFAvgPriceState state;  
  38.   
  39.         public UDAFAvgPriceEvaluator() {  
  40.             super();  
  41.             state = new UDAFAvgPriceState();  
  42.             init();  
  43.         }  
  44.   
  45.         /** 
  46.          * Reset the state of the aggregation. 
  47.          */  
  48.         public void init() {  
  49.             state.oldPriceList = new ArrayList<Integer>();  
  50.             state.newPriceList = new ArrayList<Integer>();  
  51.         }  
  52.   
  53.         /** 
  54.          * Iterate through one row of original data. 
  55.          *  
  56.          * The number and type of arguments need to the same as we call this 
  57.          * UDAF from Hive command line. 
  58.          *  
  59.          * This function should always return true. 
  60.          */  
  61.         public boolean iterate(Integer avgPirce, Integer old) {  
  62.             if (avgPirce != null) {  
  63.                 if (old == 1)  
  64.                     state.oldPriceList.add(avgPirce);  
  65.                 else  
  66.                     state.newPriceList.add(avgPirce);  
  67.             }  
  68.             return true;  
  69.         }  
  70.   
  71.         /** 
  72.          * Terminate a partial aggregation and return the state. If the state is 
  73.          * a primitive, just return primitive Java classes like Integer or 
  74.          * String. 
  75.          */  
  76.         public UDAFAvgPriceState terminatePartial() {  
  77.             // This is SQL standard - average of zero items should be null.  
  78.             return (state.oldPriceList == null && state.newPriceList == null) ? null  
  79.                     : state;  
  80.         }  
  81.   
  82.         /** 
  83.          * Merge with a partial aggregation. 
  84.          *  
  85.          * This function should always have a single argument which has the same 
  86.          * type as the return value of terminatePartial(). 
  87.          *  
  88.          * 合并点评平均价格列表 
  89.          */  
  90.         public boolean merge(UDAFAvgPriceState o) {  
  91.             if (o != null) {  
  92.                 state.oldPriceList.addAll(o.oldPriceList);  
  93.                 state.newPriceList.addAll(o.newPriceList);  
  94.             }  
  95.             return true;  
  96.         }  
  97.   
  98.         /** 
  99.          * Terminates the aggregation and return the final result. 计算并返回商户平均价格 
  100.          */  
  101.         public Integer terminate() {  
  102.             // This is SQL standard - average of zero items should be null.  
  103.             Integer avgPirce = 0;  
  104.             if (state.oldPriceList.size() >= 8  
  105.                     && state.newPriceList.size() >= 12) {  
  106.                 avgPirce = (CalcAvgPriceUtil.calcInterquartileMean(state.oldPriceList) * 2   
  107.                         + CalcAvgPriceUtil.calcInterquartileMean(state.newPriceList) * 8) / 10;  
  108.             } else {  
  109.                 state.newPriceList.addAll(state.oldPriceList);  
  110.                 avgPirce = CalcAvgPriceUtil.calcInterquartileMean(state.newPriceList);  
  111.             }  
  112.             return avgPirce == 0 ? null : avgPirce;  
  113.         }  
  114.     }  
  115.   
  116.     private AvgPriceUDAF() {  
  117.         // prevent instantiation  
  118.     }  
  119.   
  120. }  
参考文档:

http://svn.apache.org/viewvc/hive/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/udaf/example/UDAFExampleAvg.java?view=markup

UDAF的使用

同UDF一样,编译好jar包后,在Hive中执行

[sql] view plain copy
  1. add jar /data/deploy/honesty_online/shop_avgprice/avgprice.jar;  
  2.   
  3. CREATE TEMPORARY FUNCTION calc_avgprice AS 'com.dianping.credit.udaf.AvgPriceUDAF';   
  4.   
  5. SELECT  
  6.         A.shopid,  
  7.         calc_avgprice(A.avgprice, A.addtime) AS shop_avgprice,  
  8.         '$cal_dt' as hp_statdate  
  9.     FROM dpstg_credit_shop_avgprice_review_list A  
  10.     INNER JOIN dpstg_credit_shop_tuan_avgprice B ON A.shopid = B.shopid  
  11.     WHERE B.no_tuan_review_count >= 5 AND A.tuan_review = 0  
  12.     GROUP BY A.shopid 





-----------------------------




Hive进行UDAF开发,相对要比UDF复杂一些,不过也不是很难。

请看一个例子

package org.hrj.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.hive.serde2.io.DoubleWritable;

 

public class UDAFSum_Sample extends NumericUDAF {
    public static class Evaluator implements UDAFEvaluator {
        private boolean mEmpty;
        private double mSum;
        public Evaluator() {
            super();
            init();
        }

        public void init() {
            mSum = 0;
            mEmpty = true;
        }

        public boolean iterate(DoubleWritable o) {
            if (o != null) {
                mSum += o.get();
                mEmpty = false;
            }
            return true;
        }

        public DoubleWritable terminatePartial() {
            // This is SQL standard - sum of zero items should be null.
            return mEmpty ? null : new DoubleWritable(mSum);
        }

        public boolean merge(DoubleWritable o) {
            if (o != null) {
                mSum += o.get();
                mEmpty = false;
            }
            return true;
        }

        public DoubleWritable terminate() {
            // This is SQL standard - sum of zero items should be null.
            return mEmpty ? null : new DoubleWritable(mSum);
        }
    }
}

 

1.将java文件编译成Sum_Sample.jar

2.进入hive

hive> add jar Sum_sample.jar;

hive> create temporary function sum_test as 'com.hrj.hive.udf.UDAFSum_Sample';

hive> select sum_test(t.num) from t;

hive> drop temporary function sum_test;

hive> quit;

 

关于UDAF开发注意点:

1.需要import org.apache.hadoop.hive.ql.exec.UDAF以及org.apache.hadoop.hive.ql.exec.UDAFEvaluator,这两个包都是必须的

2.函数类需要继承UDAF类,内部类Evaluator实现UDAFEvaluator接口

3.Evaluator需要实现 init、iterate、terminatePartial、merge、terminate这几个函数

    1)init函数类似于构造函数,用于UDAF的初始化

    2)iterate接收传入的参数,并进行内部的轮转。其返回类型为boolean

    3)terminatePartial无参数,其为iterate函数轮转结束后,返回乱转数据,iterate和terminatePartial类似于hadoop的Combiner

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

    5)terminate返回最终的聚集函数结果


你可能感兴趣的:(Hive 简单UDAF开发(extends UDAF))