1. 程式人生 > >Hive使用者自定義聚合函式(UDAF)

Hive使用者自定義聚合函式(UDAF)

使用者自定義聚合函式,使用者提供的多個入參通過聚合計算(求和、求最大值、求最小值)得到一個聚合計算結果的函式。

問題:UDF也可以提供輸入多個引數然後輸出一個結果的運算,比如加法運算add(3,5),add這個UDF需要實現UDF的evaluate方法,那麼UDF和UDAF的實質分別究竟是什麼?

Java程式碼  收藏程式碼
  1. Double evaluate(Double a, Double b)  

1.什麼是UDAF

UDF只能實現一進一出的操作,如果需要實現多進一出,則需要實現UDAF。比如: Hive查詢資料時,有些聚類函式在HQL沒有自帶,需要使用者自定義實現; 使用者自定義聚合函式: Sum, Average

2.實現UFAF的步驟

  • 引入如下兩下類
Java程式碼  收藏程式碼
  1. import org.apache.hadoop.hive.ql.exec.UDAF  
  2. import org.apache.hadoop.hive.ql.exec.UDAFEvaluator  
  • 函式類需要繼承UDAF類,計算類Evaluator實現UDAFEvaluator介面
  • Evaluator需要實現UDAFEvaluator的init、iterate、terminatePartial、merge、terminate這幾個函式。

       a)init函式實現介面UDAFEvaluator的init函式。
       b)iterate接收傳入的引數,並進行內部的迭代。其返回型別為boolean。
       c)terminatePartial無引數,其為iterate函式遍歷結束後,返回遍歷得到的資料,terminatePartial類似於 hadoop的Combiner。
       d)merge接收terminatePartial的返回結果,進行資料merge操作,其返回型別為boolean。
       e)terminate返回最終的聚集函式結果。

3.例項

計算平均數

Java程式碼  收藏程式碼
  1. package hive.udaf;  
  2. import org.apache.hadoop.hive.ql.exec.UDAF;  
  3. import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;  
  4. public class Avg extends UDAF {  
  5.     public static class AvgState {  
  6.         private long mCount;  
  7.         private double mSum;  
  8.     }  
  9.     public
     static class AvgEvaluator implements UDAFEvaluator {  
  10.         AvgState state;  
  11.         public AvgEvaluator() {  
  12.             super();  
  13.             state = new AvgState();  
  14.             init();  
  15.         }  
  16.         /** 
  17.          * init函式類似於建構函式,用於UDAF的初始化 
  18.          */  
  19.         public void init() {  
  20.             state.mSum = 0;  
  21.             state.mCount = 0;  
  22.         }  
  23.         /** 
  24.          * iterate接收傳入的引數,並進行內部的輪轉。其返回型別為boolean * * @param o * @return 
  25.          */  
  26.         public boolean iterate(Double o) {  
  27.             if (o != null) {  
  28.                 state.mSum += o;  
  29.                 state.mCount++;  
  30.             }  
  31.             return true;  
  32.         }  
  33.         /** 
  34.          * terminatePartial無引數,其為iterate函式遍歷結束後,返回輪轉資料, * terminatePartial類似於hadoop的Combiner * * @return 
  35.          */  
  36.         public AvgState terminatePartial() {  
  37.             // combiner  
  38.             return state.mCount == 0 ? null : state;  
  39.         }  
  40.         /** 
  41.          * merge接收terminatePartial的返回結果,進行資料merge操作,其返回型別為boolean * * @param o * @return 
  42.          */  
  43.         public boolean merge(AvgState avgState) {  
  44.             if (avgState != null) {  
  45.                 state.mCount += avgState.mCount;  
  46.                 state.mSum += avgState.mSum;  
  47.             }  
  48.             return true;  
  49.         }  
  50.         /** 
  51.          * terminate返回最終的聚集函式結果 * * @return 
  52.          */  
  53.         public Double terminate() {  
  54.             return state.mCount == 0 ? null : Double.valueOf(state.mSum / state.mCount);  
  55.         }  
  56.     }  
  57. }  

4. Hive中使用UDAF

  • 將java檔案編譯成udaf_avg.jar
  • 進入hive客戶端新增jar包
Java程式碼  收藏程式碼
  1. hive>add jar /home/hadoop/udaf_avg.jar  
  • 建立臨時函式
Java程式碼  收藏程式碼
  1. hive>create temporary function udaf_avg 'hive.udaf.Avg'  
  • 查詢語句
Java程式碼  收藏程式碼
  1. hive>select udaf_avg(people.age) from people  
  • 銷燬臨時函式
Java程式碼  收藏程式碼
  1. hive>drop temporary function udaf_avg  

5. 總結

通過上面的介紹,可以看到UDAF的用法與UDF的區別了,UDF雖然可以接收多個入參,但是引數個數是固定的(其實也可以不固定,只要evaluate方法的引數型別是變長引數即可,但是一般不這麼用),而UDAF的入參是元素個數不固定的集合,這個集合只要可遍歷(使用Evaluator的iterate方法遍歷)即可,上面的入參是people表的所有age列。

UDF是對只有單條記錄的列進行的計算操作,而UDFA則是使用者自定義的聚類函式,是基於表的所有記錄進行的計算操作。