Hive可擴展接口UDF

Hive 可擴展接口學習筆記


Hive提供靈活的接口,以使用戶能更靈活地處理數據。可擴展接口分爲三種:UDF、UDTF、和UDAF

UDF

UDF是最常用到的接口,用來處理字段並返回一個單一的值。

  1. 接口類型:

    UDF提供兩種接口:

    1. 簡單API org.apache.hadoop.hive.ql.exec.UDF

      UDF接口可以用來讀取並返回初級類型。這裏說的初級類型指的是hadoop和hive的可寫類型:Text, IntWritable, LongWritable,
      DoubleWritable等。

    2. 複雜API org.apache.hadoop.hive.ql.udf.generic.GenericUDF

      GenericUDF接口可以用來處理內嵌的數據結構,像Map, List和Set.

  2. 使用舉例(簡單API):

    某字段由多組數據組成,數據間由逗號分隔,此UDF返回此字段內所有數據之和

    package com.dokia.hive.MyUDF;
    
    import org.apache.hadoop.hive.ql.exec.UDF;
    import org.apache.hadoop.io.Text;
    
    public class SumComma extends UDF{
        public Text evaluate(final Text s) {
            if (s == null) return null;
            String[] nums = s.toString().split(",");
            long sum = 0;
            for (String num : nums) {
                try {
                    long data = Long.parseLong(num);
                    sum += data;
                } catch (NumberFormatException ex) {}
            }
            return new Text(String.valueOf(sum));
        }
    }
    

    將此類打包成SumComma.jar,並加載到hive中,有三種方法:

    • 臨時添加UDF,回話結束後函數自動銷燬,每次新回話需要add jar並且create temporary function

      > add jar SumComma.jar;
      > create temporary function sum_comma as 'com.dokia.hive.MyUDF.SumComma';
      

      然後就可以在sql中使用函數sum_comma了。

    • 也可以將上述命令通過文件導入hive,獲得的同樣是臨時函數

      $ hive -i hive_init;
      
    • 自定義UDF註冊爲hive內置函數,比較危險,而且需要編譯hive,不建議

      參考資料: hive利器 自定義UDF+重編譯hive

    UDF中需要注意字段爲null的情況,因爲在數據庫中null字段還是很常見的。

  3. 使用舉例(複雜API):

    GenericUDF接口的繼承需要實現三個方法:

    // 處理字段的方法
    abstract Object evaluate evaluate(GenericUDF.DeferredObject[] arguments);
    // 返回一個字符串,表示函數名稱
    abstract String getDisplayString(String[] children);
    // 在處理字段之前檢測字段的類型
    abstract ObjectInspector initialize(ObjectInspector[] arguments);
    
  4. Maven依賴

    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.6.0</version>
    </dependency>   
    

UDTF

UDTF可以輸出多行多列

使用UDTF需要實現接口 org.apache.hadoop.hive.ql.udf.generic.GenericUDTF, 並實現其三個方法:

// 判別輸入輸出格式
abstract StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException;
// 處理輸入數據,並輸出處理後的結構
abstract void process(Object[] record) throws HiveException;
// 通知UDTF數據已經處理完
abstruct void close() throws HiveException;

Hive sql使用接口:

# 從people表格中獲取name, 並將其拆分爲name和surname兩部分輸出
SELECT
    adTable.name,
    adTable.surname
FROM people
    lateral view process_names(name) adTable as name, surname;

UDAF

UDAF可以一次處理一整個列的數據,並進行聚合操作.(類似於sum()和count())

使用UDAF需要實現兩個接口:

org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver
org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator

前者檢查輸入參數,確定需要使用的reslover的類型,後者是處理數據邏輯的主要部分,需要實現以下幾個方法:

// 確定輸入輸出數據的類型
public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException;
// 存儲數據處理結果 (中間結果和最終結果)
abstract AggregationBuffer getNewAggregationBuffer() throws HiveException;
// 重新設置聚合buffer
public void reset(AggregationBuffer agg) throws HiveException;
// 從輸入表格中讀數據 a typical Mapper
public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException;
// 處理部分數據
public Object terminalPartial(AggregationBuffer agg) throws HiveException;
// 把部分聚合結果相加
public void merge(AggregationBuffer agg, Object partial) throws HiveException;
// 輸出最終結果 the Reducer
public Object terminate(AggregationBuffer agg) throws HiveException;

參考文檔:

Apache Hive Customization Tutorial Series

Hive Extension Examples

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