Hive 可擴展接口學習筆記
Hive提供靈活的接口,以使用戶能更靈活地處理數據。可擴展接口分爲三種:UDF、UDTF、和UDAF
UDF
UDF是最常用到的接口,用來處理字段並返回一個單一的值。
接口類型:
UDF提供兩種接口:
簡單API
org.apache.hadoop.hive.ql.exec.UDF
UDF接口可以用來讀取並返回初級類型。這裏說的初級類型指的是hadoop和hive的可寫類型:Text, IntWritable, LongWritable,
DoubleWritable等。複雜API
org.apache.hadoop.hive.ql.udf.generic.GenericUDF
GenericUDF接口可以用來處理內嵌的數據結構,像Map, List和Set.
使用舉例(簡單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字段還是很常見的。
使用舉例(複雜API):
GenericUDF接口的繼承需要實現三個方法:
// 處理字段的方法 abstract Object evaluate evaluate(GenericUDF.DeferredObject[] arguments); // 返回一個字符串,表示函數名稱 abstract String getDisplayString(String[] children); // 在處理字段之前檢測字段的類型 abstract ObjectInspector initialize(ObjectInspector[] arguments);
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;