学习笔记Hive(七)—— 自定义函数
一、自定義函數簡介
1.1、函數類型
UDF:用戶定義函數
UDF操作作用于單個數據行,并且產生一個數據行作為輸出。大多數函數都屬于這一類(比如數學函數和字符串函數)
UDAF:用戶定義聚集函數
UDAF 接受多個輸入數據行,并產生一個輸出數據行。像COUNT和MAX這樣的函數就是聚集函數。
UDTF:用戶定義表生成函數
UDTF 操作作用于單個數據行,并且產生多個數據行。比如explode。
二、自定義UDF
定義一個udf,實現根據輸入的日期,輸出一個時段, 2:00-5:00凌晨,5:00-12:00為上午,12:00-14:00為中午,14:00-17:00為下午,17:00-19:00為傍晚,19:00-23:00為晚上,23:00-2:00為深夜
- 繼承UDF
- 定義evaluate方法
測試數據:
2.1、步驟:創建臨時函數或永久函數
1、創建臨時函數
1.上傳自定義udf的jar到Linux (將自定義函數打包成datetime.jar并長傳到/opt下)
2.在Hive CLI執行:add jar /opt/dateudf.jar;
3.在Hive CLI執行:create temporary function datetotime as 'demo.DateUDF';
(注意:創建臨時函數只有退出hive就不能再使用)
2、創建永久函數
1.把自定義函數的jar上傳到hdfs中
2.創建永久函數:create function datetotime as 'demo.DateUDF' using jar 'hdfs://master:8020/user/root/dateudf.jar’;
2.2、刪除自定義函數
刪除函數:drop [temporary] function [if exists] [dbname.]函數名;
例:刪除永久函數(臨時的就沒必要了,因為一退出就沒了)
三、自定義UDAF
求平均數
1.需繼承UDAF;
2.內部靜態類需繼承UDAFEvaluator抽象類,重寫方法init(),iterate(),terminatePartial(),merge(),terminate()。
測試數據:
自定義函數:
package demo;import org.apache.hadoop.hive.ql.exec.UDAF; import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;public class UDAFAverage extends UDAF{public static class AvgStat{private int mcount;private double msum;} public static class AvgEvaluator implements UDAFAverage{AvgStat avgStat;public AvgEvaluator() {super();avgStat=new AvgStat();init(); }@Overridepublic void init() {avgStat.mcount=0;avgStat.msum=0;}/*** 介紹原始數據并進行內部輪轉* @return*/public boolean iterate(Double o) {if(o!=null) {avgStat.mcount++;avgStat.msum+=o;}return true;}/*** 接收iterate遍歷結束后的輸出結果進行初次聚集,類似Combiner* @return*/public AvgStat terminatePartial() {if(avgStat.mcount==0)return null;else return avgStat;}public boolean merge(AvgStat otheravgState) {if(otheravgState!=null) {avgStat.mcount+=otheravgState.mcount;avgStat.msum+=otheravgState.msum;}return true;}/*** terminate返回最終的聚集函數結果 * * @return*/public Double terminate() {if(avgStat.mcount==0)return null;else return avgStat.msum/avgStat.mcount; }} }接下來就是創建臨時函數或永久函數了。。。
四、自定義UDTF
定義一個UDTF,可以將“商品1:價格1,商品2:價格2”格式的一列數據解析成商品,價格兩個字段
1.繼承GenericUDTF,實現initialize, process, close三個方法
2.其中initialize方法主要是判斷輸入類型并確定返回的字段類型。
3.process方法對udft函數輸入的每一行進行操作,通過調用forward方法返回一行或多行數據。
4.close方法在process調用結束后調用,用于進行其它一些額外操作,只執行一次。
測試數據:
shop1:20,shop2:30 shop3:40,shop4:30,shop5:10自定義函數:
import java.util.ArrayList;import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; 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.PrimitiveObjectInspector.PrimitiveCategory; import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;public class UDTFExplode extends GenericUDTF{/*** 進行輸入類型判斷,定義輸出字段和類型* 輔助類objectInspector幫助使用者訪問需要序列化或者反序列化的對象*/ @Overridepublic StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {if(argOIs.length!=1) {throw new UDFArgumentLengthException("UDTFExplode takes only one argument");}if(argOIs[0].getCategory()!=ObjectInspector.Category.PRIMITIVE) {throw new UDFArgumentException("UDTFExplode takes string as a parameter");}ArrayList<String> fieldNames = new ArrayList<String>(); ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();fieldNames.add("shop");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);fieldNames.add("volume");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs);}@Overridepublic void close() throws HiveException {// TODO Auto-generated method stub} /*** 處理輸入的數據:商品1:銷量1,商品2:銷量2....* 返回多行,每行新增兩個字段shop,volumn*/ @Overridepublic void process(Object[] arg0) throws HiveException {String[] input = arg0[0].toString().split(",");for(String shop_vol:input) {String[] input_split = shop_vol.split(":");forward(input_split);}} }接下來就是創建臨時函數或永久函數了。。。
4.1、UDTF使用方法
1、直接在select中使用
(udtfexplode:自定義函數)
2、和lateral view一起使用,執行過程相當于單獨執行了兩次抽取,然后合并到一個表里。
select datetime,t.shop,t.volume from test lateral view udtfexplode(datetime) t as shop,volume;總結
以上是生活随笔為你收集整理的学习笔记Hive(七)—— 自定义函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记Hive(六) —— Hive开
- 下一篇: 学习笔记Hive(八)—— 查询优化