Hive自定義UDF和聚合函數UDAF

       Hive是一種構建在Hadoop上的數據倉庫,Hive把SQL查詢轉換爲一系列在Hadoop集羣中運行的MapReduce作業,是MapReduce更高層次的抽象,不用編寫具體的MapReduce方法。Hive將數據組織爲表,這就使得HDFS上的數據有了結構,元數據即表的模式,都存儲在名爲metastore的數據庫中。

       可以在hive的外殼環境中直接使用dfs訪問hadoop的文件系統命令。

       Hive可以允許用戶編寫自己定義的函數UDF,來在查詢中使用。Hive中有3種UDF:

       UDF:操作單個數據行,產生單個數據行;

       UDAF:操作多個數據行,產生一個數據行。

       UDTF:操作一個數據行,產生多個數據行一個表作爲輸出。

      用戶構建的UDF使用過程如下:

      第一步:繼承UDF或者UDAF或者UDTF,實現特定的方法。

      第二步:將寫好的類打包爲jar。如hivefirst.jar.

      第三步:進入到Hive外殼環境中,利用add jar /home/hadoop/hivefirst.jar.註冊該jar文件

      第四步:爲該類起一個別名,create temporary function mylength as 'com.whut.StringLength';這裏注意UDF只是爲這個Hive會話臨時定義的。

      第五步:在select中使用mylength();


自定義UDF

package whut;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
//UDF是作用於單個數據行,產生一個數據行
//用戶必須要繼承UDF,且必須至少實現一個evalute方法,該方法並不在UDF中
//但是Hive會檢查用戶的UDF是否擁有一個evalute方法
public class Strip extends UDF{
    private Text result=new Text();
    //自定義方法
    public Text evaluate(Text str)
    {
      if(str==null)
        return null;
        result.set(StringUtils.strip(str.toString()));
        return result;
    }
    public Text evaluate(Text str,String stripChars)
    {
        if(str==null)
            return null;
        result.set(StringUtils.strip(str.toString(),stripChars));
        return result;
    }
}

注意事項:

   1,一個用戶UDF必須繼承org.apache.hadoop.hive.ql.exec.UDF;

   2,一個UDF必須要包含有evaluate()方法,但是該方法並不存在於UDF中。evaluate的參數個數以及類型都是用戶自己定義的。在使用的時候,Hive會調用UDF的evaluate()方法。


自定義UDAF

該UDAF主要是找到最大值

package whut;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.io.IntWritable;
//UDAF是輸入多個數據行,產生一個數據行
//用戶自定義的UDAF必須是繼承了UDAF,且內部包含多個實現了exec的靜態類
public class MaxiNumber extends UDAF{
    public static class MaxiNumberIntUDAFEvaluator implements UDAFEvaluator{
        //最終結果
        private IntWritable result;
        //負責初始化計算函數並設置它的內部狀態,result是存放最終結果的
        @Override
        public void init() {
            result=null;
        }
        //每次對一個新值進行聚集計算都會調用iterate方法
        public boolean iterate(IntWritable value)
        {
            if(value==null)
                return false;
            if(result==null)
              result=new IntWritable(value.get());
            else
              result.set(Math.max(result.get(), value.get()));
            return true;
        }
                                                                                                                                 
        //Hive需要部分聚集結果的時候會調用該方法
        //會返回一個封裝了聚集計算當前狀態的對象
        public IntWritable terminatePartial()
        {
            return result;
        }
        //合併兩個部分聚集值會調用這個方法
        public boolean merge(IntWritable other)
        {
            return iterate(other);
        }
        //Hive需要最終聚集結果時候會調用該方法
        public IntWritable terminate()
        {
            return result;
        }
    }
}

注意事項:

    1,用戶的UDAF必須繼承了org.apache.hadoop.hive.ql.exec.UDAF;

    2,用戶的UDAF必須包含至少一個實現了org.apache.hadoop.hive.ql.exec的靜態類,諸如常見的實現了 UDAFEvaluator。

    3,一個計算函數必須實現的5個方法的具體含義如下:

    init():主要是負責初始化計算函數並且重設其內部狀態,一般就是重設其內部字段。一般在靜態類中定義一個內部字段來存放最終的結果。

   iterate():每一次對一個新值進行聚集計算時候都會調用該方法,計算函數會根據聚集計算結果更新內部狀態。當輸入值合法或者正確計算了,則就返回true。

   terminatePartial():Hive需要部分聚集結果的時候會調用該方法,必須要返回一個封裝了聚集計算當前狀態的對象。

   merge():Hive進行合併一個部分聚集和另一個部分聚集的時候會調用該方法。

   terminate():Hive最終聚集結果的時候就會調用該方法。計算函數需要把狀態作爲一個值返回給用戶。

  4,部分聚集結果的數據類型和最終結果的數據類型可以不同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章