大數據Hive中的UDF:自定義數據處理的利器(下)

在上一篇文章中,我們對第一種用戶定義函數(UDF)進行了基礎介紹。接下來,本文將帶您深入了解剩余的兩種UDF函數類型。

文章目錄

    • 1. UDAF
      • 1.1 簡單UDAF
      • 1.2 通用UDAF
    • 2. UDTF
    • 3. 總結

1. UDAF

1.1 簡單UDAF

第一種方式是 Simple(簡單) 方式,即繼承 org.apache.hadoop.hive.ql.exec.UDAF 類,并在派生類中以靜態內部類的方式實現 org.apache.hadoop.hive.ql.exec.UDAFEvaluator 接口。這個計算類將負責執行具體的聚合邏輯,具體步驟如下:

a)初始化(init):首先,我們需要實現UDAFEvaluator接口的init方法,用于初始化聚合過程中所需的任何資源或狀態。

b)迭代(iterate):接下來,iterate方法將被用來處理傳入的數據。此方法將逐個接收數據項,并更新聚合狀態。它返回一個布爾值,指示是否繼續迭代或停止。

c)部分終止(terminatePartial):在迭代完成后,terminatePartial方法將被調用。它的作用類似于Hadoop中的Combiner,用于返回一個中間聚合結果,以便在多個任務之間進行合并。

d)合并(merge):merge方法用于接收來自terminatePartial的中間結果,并將其合并以形成更接近最終結果的聚合狀態。此方法同樣返回一個布爾值,指示合并操作是否成功。

e)最終終止(terminate):最后,terminate方法將被用來生成并返回聚合操作的最終結果。

import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.io.IntWritable;// 自定義的UDAF類,用于計算最大值
public class MyMaxUDAF extends UDAF {// 實現UDAFEvaluator接口的靜態內部類static public class MaxIntEvaluator implements UDAFEvaluator {// 存放當前聚合操作過程中的最大值private int mMax;// 用于標記聚合數據集是否為空private boolean mEmpty;// 構造方法,用于執行初始化操作public MaxIntEvaluator() {super();init();}// 初始化方法,用于重置聚合狀態public void init() {// 初始化最大值為0mMax = 0;// 初始化聚合數據集為空mEmpty = true;}// 迭代處理每一行數據。每次調用處理一行記錄public boolean iterate(IntWritable o) {// 檢查傳入的數據是否為nullif (o != null) {// 如果當前聚合數據集為空,則直接將當前值設置為最大值if (mEmpty) {mMax = o.get();mEmpty = false; // 更新狀態,標記聚合數據集不再為空} else {// 聚合數據集不為空時,用當前值和之前的最大值比較,保留較大的那個mMax = Math.max(mMax, o.get());}}return true;}// 輸出Map階段處理結果的方法,返回當前的最大值public IntWritable terminatePartial() {// 如果聚合數據集為空,則返回null;否則,返回當前的最大值return mEmpty ? null : new IntWritable(mMax);}// Combine/Reduce階段,合并處理結果public boolean merge(IntWritable o) {// 通過調用iterate方法進行合并操作return iterate(o);}// 返回最終的聚集函數結果public IntWritable terminate() {// 如果聚合數據集為空,則返回null;否則,返回最終的最大值return mEmpty ? null : new IntWritable(mMax);}}
}

1.2 通用UDAF

編寫簡單的UDAF(用戶定義聚合函數)相對容易,但這種方法由于依賴Java的反射機制,可能會犧牲一些性能,并且它不支持變長參數等高級特性。相比之下,通用UDAF(Generic UDAF)提供了這些高級特性的支持,雖然它的編寫可能不如簡單UDAF那樣直接明了。
Hive社區推崇使用通用UDAF作為最佳實踐,建議采用新的抽象類org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver來替代舊的UDAF接口,并推薦使用org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator抽象類來替換舊的UDAFEvaluator接口。這種新方法不僅提升了性能,還增加了靈活性,使得UDAF的功能更加強大和多樣化。

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.apache.hadoop.io.IntWritable;// 通過繼承AbstractGenericUDAFResolver并使用Description注解來定義一個新的UDAF。
@Description(name = "max_int", value = "_FUNC_(int) - Returns the maximum value of the column")
public class MyMaxUDAF2 extends AbstractGenericUDAFResolver {// 聚合函數的求值器內部類,繼承自GenericUDAFEvaluator。public static class MaxIntEvaluator extends GenericUDAFEvaluator {// 用于存儲輸入參數的ObjectInspector。private PrimitiveObjectInspector inputOI;// 用于存儲聚合結果。private IntWritable result;// 初始化方法,用于設置聚合函數的參數和返回類型。@Overridepublic ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {super.init(m, parameters);// 確認參數是原始類型并初始化inputOI。inputOI = (PrimitiveObjectInspector) parameters[0];// 設置聚合函數的返回類型為可寫的整型。return PrimitiveObjectInspectorFactory.writableIntObjectInspector;}// 創建聚合緩沖區對象的方法。@Overridepublic AggregationBuffer getNewAggregationBuffer() throws HiveException {MaxAggBuffer buffer = new MaxAggBuffer();reset(buffer);return buffer;}// 重置聚合緩沖區對象的方法。@Overridepublic void reset(AggregationBuffer agg) throws HiveException {((MaxAggBuffer) agg).setValue(Integer.MIN_VALUE);}// 迭代方法,用于處理每一行數據。@Overridepublic void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {if (parameters[0] != null) {MaxAggBuffer myagg = (MaxAggBuffer) agg;// 從參數中獲取整數值并更新聚合緩沖區中的最大值。int value = PrimitiveObjectInspectorUtils.getInt(parameters[0], inputOI);if (value > myagg.value) {myagg.setValue(value);}}}// 終止部分聚合的方法,通常返回最終聚合結果。@Overridepublic Object terminatePartial(AggregationBuffer agg) throws HiveException {return terminate(agg);}// 合并部分聚合結果的方法。@Overridepublic void merge(AggregationBuffer agg, Object partial) throws HiveException {if (partial != null) {MaxAggBuffer myagg = (MaxAggBuffer) agg;// 從部分聚合結果中獲取整數值并更新聚合緩沖區中的最大值。int partialValue = PrimitiveObjectInspectorUtils.getInt(partial, inputOI);if (partialValue > myagg.value) {myagg.setValue(partialValue);}}}// 終止方法,用于返回最終聚合結果。@Overridepublic Object terminate(AggregationBuffer agg) throws HiveException {MaxAggBuffer myagg = (MaxAggBuffer) agg;// 創建IntWritable對象并設置聚合結果,然后返回。result = new IntWritable(myagg.value);return result;}// 聚合緩沖區對象的內部類定義,用于存儲聚合過程中的中間狀態。static class MaxAggBuffer implements AggregationBuffer {int value; // 聚合緩沖區中的值// 設置聚合緩沖區中的值void setValue(int val) { value = val; }}}
}
特性/UDAF類型簡單UDAF通用UDAF
性能依賴反射,性能較低不依賴反射,性能較高
參數靈活性不支持變長參數支持變長參數
易用性編寫簡單直觀編寫復雜,功能強大
推薦使用適合簡單聚合操作適合復雜聚合邏輯和高性能需求
接口和抽象類舊的UDAF接口和UDAFEvaluator新的AbstractGenericUDAFResolverGenericUDAFEvaluator
功能特性功能有限,實現常見聚合支持復雜迭代邏輯和自定義終止邏輯
應用場景- 快速開發和原型設計
- 實現基本聚合操作,如求和、平均值
- 對性能要求不高的小型項目
- 實現復雜的數據分析和處理
- 大數據量處理,需要高性能
- 需要變長參數支持的復雜查詢
- 高級功能實現,如窗口函數、復雜的分組聚合

選擇UDAF類型時應根據實際需求和上述特性來決定,以確保既能滿足功能需求,又能獲得較好的性能表現。

2. UDTF

  • 繼承GenericUDTF類的步驟:
    開發自定義的表生成函數(UDTF)時,首先需要繼承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF這個抽象類,它為UDTF提供了一個通用的實現框架。

  • 實現initialize()、process()和close()方法:
    為了完成自定義UDTF的功能,需要實現三個核心方法:initialize()用于初始化UDTF,process()用于處理輸入數據并生成輸出,close()用于執行清理操作。

    - initialize()方法的調用與作用:在UDTF的執行過程中,initialize()方法是首先被調用的。它負責初始化UDTF的狀態,并返回關于UDTF返回行的信息,包括返回行的個數和類型。

    • process()方法的執行:initialize()方法執行完成后,接下來會調用process()方法。該方法是UDTF的核心,負責對輸入參數進行處理。在process()方法中,可以通過調用forward()方法將處理結果逐行返回。
    • close()方法的清理作用:在UDTF的所有處理工作完成后,最終會調用close()方法。這個方法用于執行必要的清理工作,如釋放資源或關閉文件句柄等,確保UDTF在結束時不會留下任何未處理的事務。

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;import java.util.ArrayList;
import java.util.List;/*** 自定義一個UDTF,實現將一個由任意分割符分隔的字符串切割成獨立的單詞。**/
public class LineToWordUDTF extends GenericUDTF {// 用于存儲輸出單詞的集合private ArrayList<String> outList = new ArrayList<String>();/*** initialize方法:當GenericUDTF函數初始化時被調用一次,用于執行一些初始化操作。* 包括:*      1. 判斷函數參數個數*      2. 判斷函數參數類型*      3. 確定函數返回值類型*/@Overridepublic StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {// 1. 定義輸出數據的列名和類型List<String> fieldNames = new ArrayList<String>();List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();// 2. 添加輸出數據的列名和類型fieldNames.add("lineToWord"); // 輸出列名fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); // 輸出列類型// 返回輸出數據的ObjectInspectorreturn ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);}/*** process方法:自定義UDTF的核心邏輯實現方法。* 代碼實現步驟可以分為三部分:*  1. 參數接收*  2. 自定義UDTF核心邏輯*  3. 輸出結果*/@Overridepublic void process(Object[] objects) throws HiveException {// 1. 獲取原始數據String arg = objects[0].toString(); // 假設第一個參數為要分割的字符串// 2. 獲取數據傳入的第二個參數,此處為分隔符String splitKey = objects[1].toString(); // 假設第二個參數為分隔符// 3. 將原始數據按照傳入的分隔符進行切分String[] fields = arg.split(splitKey); // 分割字符串// 4. 遍歷切分后的結果,并寫出for(String field : fields) {// 集合為復用的,首先清空集合outList.clear();// 將每個單詞添加至集合outList.add(field);// 將集合內容通過forward方法寫出,這里假設forward方法可以處理集合forward(outList);}}/*** close方法:當沒有其他輸入行時,調用該函數。* 可以進行一些資源關閉處理等最終處理。*/@Overridepublic void close() throws HiveException {// 資源清理邏輯,當前示例中無具體實現}}

3. 總結

本文我們詳細解析了UDAF和UDTF在Hive中的應用。通過實際代碼示例,我們展示了UDAF如何幫助我們深入分析數據,以及UDTF如何簡化復雜的數據轉換任務。

感謝您的閱讀和支持。如果您對UDAF、UDTF或Hive的其他高級功能有疑問,或者想要更深入地討論,歡迎在文章下留言或直接聯系我們。期待我們的下一次分享,一起在大數據的世界里探索新知。

再次感謝,希望您喜歡這次的分享。我們下次見!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/14460.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/14460.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/14460.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每日一題《leetcode--382.鏈表隨機結點》

https://leetcode.cn/problems/linked-list-random-node/ 這道題我們首先看到題目中的要求&#xff1a;在單鏈表中隨機選取一個鏈表中的結點&#xff0c;要使每個結點被選取的概率是一樣的。 當我們看到隨機這兩個字時&#xff0c;應該就會想起rand()這個函數。接著我們把使用這…

[暈事]今天做了件暈事35 VM發送給gateway太多ARP,導致攻擊檢查?

最近遇到一個問題&#xff0c;說網關學不到新起來VM的mac地址&#xff0c;通過tshark抓包發現&#xff0c;VM已經發出去GARP了。而且連續發送了24個GARP。 就認為是網關的問題&#xff0c;為什么沒網關沒有學到&#xff1f;就讓測試同事開網絡設備的ticket。 后來聽同事說&…

自己搭建內網穿透

本文介紹使用最新版frp搭建內網穿透&#xff0c;最新版本的frp在配置上與之前有很大不同&#xff0c;需要使用.toml文件進行配置。其中主要問題出現在toml文件內部。 一、云服務器配置 下載frp sudo apt update sudo apt install wget wget https://github.com/fatedier/frp…

求出這行英文中最后一個單詞的長度

【題目描述】藍寶看到了一行奇怪的英文&#xff0c;這行英文由若干單詞組成&#xff0c;每個單詞前后用一些字符*隔開請幫助藍寶求出這行英文中最后一個單詞的長度。【輸入格式】 輸入一行&#xff0c;就就是藍寶看到的奇怪的英文。 【輸出格式】 輸出一行&#xff0c;是個整數…

文旅3d仿真數字人形象為游客提供全方位的便捷服務

在AI人工智能與VR虛擬現實技術的雙重驅動下&#xff0c;文旅3D數字代言人正以其獨特的魅力&#xff0c;頻頻亮相于各類文旅場景&#xff0c;為游客帶來前所未有的個性化服務體驗。他們不僅有趣有品&#xff0c;更能言善道&#xff0c;成為文旅業數字化發展的新亮點。 這些文旅3…

Android 文件加密解密(AES)

private static final String ALGORITHM "AES"; 文件加密 /*** 文件加密* param secretKey 文件加密密鑰* param oldFiles 原始文件列表&#xff0c;需要加密的* param newFiles 構造加密后的文件列表*&#xff08;選擇多個或者單個&#xff09;多個文件加密*/ Re…

我的文章分類合集目錄

文章目錄 Java相關基礎常規問題類Docker類RabbitMQ類分庫分表 網絡工程相關路由交換、Cisco Packet TracerIP地址 前端相關數據庫 Java相關 基礎 Java開發規范、項目開發流程 SpringBoot整合MyBatis實現增刪改查(簡單,詳細) SpringBoot整合MybatisPlus&#xff08;詳細&#…

【Muduo】TcpConnection類

Muduo網絡庫的TcpConnection類代表了TCP連接的一端&#xff0c;即服務器與遠程對等端之間的連接。TcpConnection類知道自身和對端的InetAddress、封裝了前面講過的Socket類和Channel類&#xff0c;并且保有管理自己的subLoop指針&#xff0c;還有多種事件處理函數和回調&#x…

【搜索】BFS

#include <iostream> #include <cstring> #include <queue>using namespace std;const int N 110;typedef pair<int, int> PII;int n, m; int g[N][N], d[N][N];//存放地圖//存每一個點到起點的距離int bfs() {queue< PII > q;q.push({0, 0});m…

C語言什么是位段?其優點是什么?

一、問題 在內存中&#xff0c;1byte 8bit&#xff0c;即 1 字節等于 8 位。位由兩個值組成&#xff0c;即 0 和 1 。因此&#xff0c;存儲在計算機中的 1 字節&#xff0c;可以看成是8個?進制數字&#xff08;0 和1&#xff09;組成的串。了解了內存空間的最?單位&#xff…

16.js數學方法和進制轉換

數學方法 &#xff08;1&#xff09;Math.random() 默認生成0-1的隨機數 var resMath.random() console.log(res) &#xff08;2&#xff09;Math.round(數字) 取整&#xff1a;正數-四舍五入 負數-5舍6入 var resMath.round(11)console.log(res) //11var res1Math.round(1…

Aerospike設置日志按日期保存及日志保存日期

配置文件位置&#xff1a;/etc/aerospike/aerospike.conf 是Aerospike的主配置文件&#xff0c;其中包含了日志配置以及其他各種設置。 日志配置&#xff1a;在aerospike.conf文件中&#xff0c;找到logging部分進行配置。以下是一個示例配置&#xff1a; logging { # 日志文…

CentOS7安裝內網穿透實現遠程推送鏡像到本地Docker Registry

文章目錄 前言1. 部署Docker Registry2. 本地測試推送鏡像3. Linux 安裝cpolar4. 配置Docker Registry公網訪問地址5. 公網遠程推送Docker Registry6. 固定Docker Registry公網地址 前言 本文主要介紹如何部署Docker Registry 本地鏡像倉庫,簡單幾步結合cpolar內網穿透工具實現…

網絡安全之重發布與路由策略詳解

重發布&#xff1b;import &#xff08;路由導入&#xff09; 將不同方式&#xff08;直連、靜態、缺省、其他協議&#xff09;的路由器重發布進入RIP&#xff0c;OSPF中。 注意&#xff1a;1、華為中不能將缺省路由重發布進入RUO協議&#xff08;思科也是一樣&#xff09;。…

Mac下QT開發環境搭建詳細教程

QT Qt是一個跨平臺的C應用程序框架&#xff0c;用于開發具有圖形用戶界面&#xff08;GUI&#xff09;的應用程序&#xff0c;同時也可用于開發非GUI程序&#xff0c;比如控制臺工具和服務器。Qt是設計成通用、可移植和高效的&#xff0c;它廣泛應用于全球的企業和開發者社區中…

青少年 CTF 練習平臺:Misc(一)

前言 當然&#xff0c;我可以更詳細地介紹一下青少年CTF練習平臺。 青少年CTF練習平臺是一個專為青少年設計的網絡安全競賽和訓練平臺。該平臺由思而聽&#xff08;山東&#xff09;網絡科技有限公司與克拉瑪依市思而聽網絡科技有限公司共同建設&#xff0c;自2018年創建以來…

圖論定理匯總(二)

第六章 平面圖 (一)、平面圖的概念 定義1 如果能把圖 G G G畫在平面上&#xff0c;使得除頂點外&#xff0c;邊與邊之間沒有交叉&#xff0c;稱 G G G可嵌入平面&#xff0c;或稱 G G G是可平面圖。可平面圖 G G G的邊不交叉的一種畫法&#xff0c;稱為 G G G的一種平面嵌入&…

入門四認識HTML

一、HTML介紹 1、Web前端三大核心技術 HTML&#xff1a;負責網頁的架構 CSS&#xff1a;負責網頁的樣式、美化 JS&#xff1a;負責網頁的行動 2、什么是HTML HTML是用來描述網頁的一種語言。 3、Html標簽 單標簽<html> 雙標簽<h>內容</h> 4、標…

spring boot整合j2cache 關閉二級緩存

我們整合了 j2cache 的項目啟動 日志會輸出 一級緩存 二級緩存 一級是 EhCacheProvider 二級是 SpringRedisProvider 如果 我們不想用二級緩存 在 j2cache.properties 中 加上 j2cache.12-cache-open配置 值為 true/false true是啟用二級緩存 false 是不起用 默認 true 所以 …

多輸入多輸出 | Matlab實現GA-CNN遺傳算法優化卷積神經網絡多輸入多輸出預測

多輸入多輸出 | Matlab實現GA-CNN遺傳算法優化卷積神經網絡多輸入多輸出預測 目錄 多輸入多輸出 | Matlab實現GA-CNN遺傳算法優化卷積神經網絡多輸入多輸出預測預測效果基本介紹程序設計參考資料 預測效果 基本介紹 Matlab實現GA-CNN遺傳算法優化卷積神經網絡多輸入多輸出預測&…