hive UDF註冊以及編寫

背景

公司有個業務需求,需要對一些算子進行實現,寫UDF,剛開始打算用sql 實現,但是考慮到算子可能嵌套等複雜情況,遂用udf 去做。

UDF編寫

1、UDF數據類型

這裏先講一下UDF的數據類型,剛開始我寫UDF的時候使用java 中的bigDecimal 等數據類型發現是不行的。然後我開始找hive 相關的數據類型。發現網上寫的也少,然後我在想hive內置的函數爲什麼支持decimal,long的數據類型呢。我就在github中的hive的源碼裏全局查找hive的內置函數,爲了方便查找,我找了個複雜一些的內置函數查找。然後找到了
https://github.com/apache/hive/blob/91a92e323a29a49b5ad3b860b9523f347b6b8d4c/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
這一個註冊函數的類。然後我隨便選取了 ceil 這個函數,看看他是怎麼對數據進行的處理,然後發現了hive支持的數據類型,參照下面源代碼

public final class GenericUDFCeil extends GenericUDFFloorCeilBase {

  public GenericUDFCeil() {
    super();
    opDisplayName = "ceil";
  }

  @Override
  protected LongWritable evaluate(DoubleWritable input) {
    longWritable.set((long) Math.ceil(input.get()));
    return longWritable;
  }

  @Override
  protected HiveDecimalWritable evaluate(HiveDecimalWritable input) {
    decimalWritable.set(input);
    decimalWritable.mutateSetScale(0, HiveDecimal.ROUND_CEILING);
    return decimalWritable;
  }

這樣就迎刃而解了。編寫UDF 的數據類型是
HiveDecimalWritable,DoubleWritable,LongWritable 等 岔開一句 我發現 Long 和String 也是支持的。

2、編寫UDF

只要集成UDF類然後重寫evaluate 方法就好了,這塊沒什麼好說的。
唯一一點就是如果想要接入不同的參數,重載方法就好,像我上面的ceil內置函數的源碼一樣
如下圖所示

public class DataMaxUdf extends UDF {
    public Integer evaluate(Integer a,Integer b) {
        if (a == null || b==null) { return null; }
        return a>b?a:b;
    }
}

UDF註冊

註冊UDF 分爲臨時註冊和永久註冊,參考資料https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateFunction

1、 臨時函數

臨時函數以session生命週期(比如你打開關閉 hive cli 或者beeline)
示例代碼(在shell裏)

add jar /home/hadoop/zgh/hiveudf-1.0-SNAPSHOT.jar;
create temporary function ceshi as 'com.example.udf.DataMaxUdf';

這樣即可註冊一個臨時函數了。

2、永久註冊

將其打包上傳到hdfs 的目錄下,在hive cli 中執行

create function zgh.data_max as 'com.example.udf.DataMaxUdf' using jar 'hdfs:///user/zgh/hiveudf.jar';

這樣就在zgh databases 下面創建了一個 data_max的自定義函數。當每次訪問函數時,他會默認去hdfs 加載當前函數。

注意

1

、比如傳入的參數需要時bigInt格式的話,這邊就需要傳入Long 類型的格式,,比如這種,Integer類型是不支持bigInt的

public class DataMinUdf extends UDF {

    public Long evaluate(Long a, Long b) {
        if (a == null || b==null) { return null; }
        return a>b?b:a;
    }
}

2

、hiverserver2 訪問的時候發現註冊的udf 訪問不到
hive在1.2版本以後,使用jdbc 訪問hiveserver2 和hive cli 將有可能訪問不到udf。官網解釋如下

creating permanent functions in one Hive CLI session may not be reflected in HiveServer2 or other Hive CLI sessions,
 if they were started before the function was created. 
Issuing RELOAD FUNCTIONS within a HiveServer2 or HiveCLI session will allow it to pick up any changes to the permanent functions that may have been done by a different HiveCLI session.
Due to backward compatibility reasons RELOAD FUNCTION; is also accepted.

所以,在訪問udf的時候,需要先執行

RELOAD FUNCTIONS

來獲取udf的更新情況

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