簡述UDF/UDAF/UDTF是什么,各自解決問題及應用場景


UDF

  • User-Defined-Function 自定義函數 、一進一出;

  • 背景

    • 系統內置函數無法解決實際的業務問題,需要開發者自己編寫函數實現自身的業務實現訴求。
    • 應用場景非常多,面臨的業務不同導致個性化實現很多,故udf很需要。
  • 意義

    • 函數擴展得到解決,極大豐富了可定制化的業務需求。
    • IO要求-要解決的問題
      • in:out=1:1,只能輸入一條記錄當中的數據,同時返回一條處理結果。
      • 屬於最常見的自定義函數,像cos,sin,substring,indexof等均是如此要求
  • 實現步驟(Java創建自定義UDF類)

    • 自定義一個java類
    • 繼承UDF類
    • 重寫evaluate方法
    • 打包類所在項目成一個all-in-one的jar包並上傳到hive所在機器
    • 在hive中執行add jar操作,將jar加載到classpath中。
    • 在hive中創建模板函數,使得后邊可以使用該函數名稱調用實際的udf函數
    • hive sql中像調用系統函數一樣使用udf函數
  • 代碼實現

    • 功能要求:實現當輸入字符串超過2個字符的時候,多余的字符以”…”來表示。
    • 如“12”則返回“12”,如“123”返回“12…”
    • 自定義類、繼承UDF、重寫evaluate方法已在代碼中體現
import org.apache.hadoop.hive.ql.exec.UDF; /* * 功能:實現當輸入字符串超過2個字符的時候,多余的字符以"..."來表示。 * 輸入/輸出:* 如“12”則返回“12”,如“123”返回“12..." */ public class ValueMaskUDF extends UDF{ public String evaluate(String input,int maxSaveStringLength,String replaceSign) { if(input.length()<=maxSaveStringLength){ return input; } return input.substring(0,maxSaveStringLength)+replaceSign; } public static void main(String[] args) { System.out.println(new ValueMaskUDF().evaluate("河北省",2,"..."));; } } 

UDAF

  • 自定義udaf函數self_count,實現系統udaf count的功能

  • Input/Output要求-要解決的問題

    • in:out=n:1,即接受輸入N條記錄當中的數據,同時返回一條處理結果。
    • 屬於最常見的自定義函數,像count,sum,avg,max等均是如此要求
  • 實現步驟

    • 自定義一個java類
    • 繼承UDAF類
    • 內部定義一個靜態類,實現UDAFEvaluator接口
    • 實現方法init,iterate,terminatePartial,merge,terminate,共5個方法. 詳見下圖
    • 在hive中執行add jar操作,將jar加載到classpath中。
    • 在hive中創建模板函數,使得后邊可以使用該函數名稱調用實際的udf函數
    • hive sql中像調用系統函數一樣使用udaf函數


       
      Hive_UDAF五個方法.png
  • 業務測試

輸入:


 
輸入.png

輸出:


 
輸出.png
  • UDAF代碼開發
import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.hadoop.hive.ql.exec.UDAF; import org.apache.hadoop.hive.ql.exec.UDAFEvaluator; import org.apache.log4j.Logger; /** * 實現多條數據合並成一條數據 */ // 主類繼承UDAF public class StudentScoreAggUDAF extends UDAF { // 日志對象初始化 public static Logger logger = Logger.getLogger(StudentScoreAggUDAF.class); // 靜態類實現UDAFEvaluator public static class Evaluator implements UDAFEvaluator { // 設置成員變量,存儲每個統計范圍內的總記錄數 private Map<String, String> courseScoreMap; //初始化函數,map和reduce均會執行該函數,起到初始化所需要的變量的作用 public Evaluator() { init(); } // 初始化函數間傳遞的中間變量 public void init() { courseScoreMap = new HashMap<String, String>(); } //map階段,返回值為boolean類型,當為true則程序繼續執行,當為false則程序退出 public boolean iterate(String course, String score) { if (course == null || score == null) { return true; } courseScoreMap.put(course, score); return true; } /** * 類似於combiner,在map范圍內做部分聚合,將結果傳給merge函數中的形參mapOutput * 如果需要聚合,則對iterator返回的結果處理,否則直接返回iterator的結果即可 */ public Map<String, String> terminatePartial() { return courseScoreMap; } // reduce 階段,用於逐個迭代處理map當中每個不同key對應的 terminatePartial的結果 public boolean merge(Map<String, String> mapOutput) { this.courseScoreMap.putAll(mapOutput); return true; } // 處理merge計算完成后的結果,即對merge完成后的結果做最后的業務處理 public String terminate() { return courseScoreMap.toString(); } } } 

測試sql語句

select id,username,score_agg(course,score) from student_score group by id,username; 

UDTF

  • User-Defined Table-Generating Functions
  • 要解決一行輸入多行輸出的問題,問題的應用場景不少
  • 用udtf解決一行輸入多行輸出的不多,往往被lateral view explode+udf等替代實現,比直接用udtf會更簡單、直接一些


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM