Hive自訂函數UDF、UDTF、UDAF入門
詳細講解Hive自訂函數UDF、UDTF、UDAF基礎知識,帶你快速入門,首先在Hive中建立表”apache_log”
CREATE TABLE apachelog (
host STRING,
identity STRING,
user STRING,
time STRING,
request STRING,
status STRING,
size STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.Hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]*\\]]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*) (?: ([^ \"]*|\".*\") ([^ \"]*|\".*\"))?"
)
STORED AS TEXTFILE;
這個是官方給出的執行個體,但是是錯的。
不過,已經有人給做出了修改。
接下來結合一些範例資料
27.19.74.143 - - [29/April/2016:17:38:20 +0800] "GET /static/image/common/faq.gif HTTP/1.1" 200 1127
110.52.250.126 - - [29/April/2016:17:38:20 +0800] "GET /data/cache/style_1_widthauto.css?y7a HTTP/1.1" 200 1292
27.19.74.143 - - [29/April/2016:17:38:20 +0800] "GET /static/image/common/hot_1.gif HTTP/1.1" 200 680
27.19.74.143 - - [29/April/2016:17:38:20 +0800] "GET /static/image/common/hot_2.gif HTTP/1.1" 200 682
27.19.74.143 - - [29/April/2016:17:38:20 +0800] "GET /static/image/filetype/common.gif HTTP/1.1" 200 90
110.52.250.126 - - [29/April/2016:17:38:20 +0800] "GET /source/plugin/wsh_wx/img/wsh_zk.css HTTP/1.1" 200 1482
110.52.250.126 - - [29/April/2016:17:38:20 +0800] "GET /data/cache/style_1_forum_index.css?y7a HTTP/1.1" 200 2331
110.52.250.126 - - [29/April/2016:17:38:20 +0800] "GET /source/plugin/wsh_wx/img/wx_jqr.gif HTTP/1.1" 200 1770
27.19.74.143 - - [29/April/2016:17:38:20 +0800] "GET /static/image/common/recommend_1.gif HTTP/1.1" 200 1028
110.52.250.126 - - [29/April/2016:17:38:20 +0800] "GET /static/image/common/logo.png HTTP/1.1" 200 4542
......
這個是apache伺服器的日誌資訊,一共七個欄位,分別表示:”host”、”identity”、”user”、”time”、”request”、”status”、”size”,在hive官網上是有九個欄位的,剩下兩個為:”referer”、”agent”。
------------------------------------------分割線------------------------------------------
範例資料相關資料可從以下資訊得到下載:
點擊這個 連結關注 幫客之家官方,關注後回複數字151443。即可得到網友的分享密碼。
如果取消追蹤幫客之家公眾號,即使再次關注,也將無法提供本服務!
連結:https://pan.baidu.com/s/1dvBorZch0WFPMPO2xqZTLQ 密碼:獲得見上面的方法,地址失效請在下面留言。
------------------------------------------分割線------------------------------------------
我們根據這些資料,從一些小需求中來體會一下這三種函數。
UDF(user-defined functions)
“小”需求:
提取”time”,轉換成”yyyy-MM-dd HH:mm:ss” 格式。
要點:
1.繼承自“org.apache.hadoop.hive.ql.exec.UDF”;
2.實現”evaluate()”方法。
*JAVA 代碼*
package com.hadoop.hivetest.udf;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.apache.hadoop.hive.ql.exec.UDF;
public class MyDateParser extends UDF{
public String evaluate(String s){
SimpleDateFormat formator = new SimpleDateFormat("dd/MMMMM/yyyy:HH:mm:ss Z",Locale.ENGLISH);
if(s.indexOf("[")>-1){
s = s.replace("[", "");
}
if(s.indexOf("]")>-1){
s = s.replace("]", "");
}
try {
//將輸入的string轉換成date資料類型
Date date = formator.parse(s);
SimpleDateFormat rformator = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return rformator.format(date);
} catch (ParseException e) {
e.printStackTrace();
return "";
}
}
}
小插曲
匯出為jar包,發送到Linux上。這次我們可以使用 editplus 編輯器來上傳:
– 開啟editplus,選擇”File—FTP—FTP Setting” –
– 選擇添加 –
並且在相應的欄位上填上值,對於”Subdirectory”這一項要填寫的是你希望上傳到Linux上的哪個目錄。
– 點擊”Advanced Options” –
之後便可以一路OK回去。
– 選擇FTP Upload –
在這裡找到要上傳的檔案,選擇要上傳到哪一個賬戶上,並選擇”Upload”即可。
然後我們就可以在”Subdirectory”中寫到的目錄下去找我們的檔案了。
– 小插曲結束 –
之後我們使用beeline用戶端來串連hive
然後我們可以建立一個資料庫,並使用之前的建表語句來建立”apache_log”,並匯入資料(預設大家都會了^.^)。
Step 1: add jar “jar-path”
Step 2: create function timeparse as ‘包名+類名’
Step 3: 使用該函數
對比之前我們匯入的資料
UDTF(user-defined table-generating functions)
“小”需求:
針對”request”欄位,將其拆分,擷取到使用者的請求串連。
第一部分表示請求的方式,第二部分為使用者請求的串連,第三部分為協及版本號碼。
要點:
1.繼承自”org.apache.hadoop.hive.ql.udf.generic.GenericUDTF”;
2.實現initialize()、process()、close()三個方法。
*JAVA代碼
package com.hadoop.hivetest.udf;
import java.util.ArrayList;
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;
public class MyRequestParser extends GenericUDTF {
@Override
public StructObjectInspector initialize(ObjectInspector[] arg0) throws UDFArgumentException {
if(arg0.length != 1){
throw new UDFArgumentException("參數不正確。");
}
ArrayList<String> fieldNames = new ArrayList<String>();
ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
//添加返回欄位設定
fieldNames.add("rcol1");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
fieldNames.add("rcol2");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
fieldNames.add("rcol3");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
//將返回欄位設定到該UDTF的傳回值類型中
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
@Override
public void close() throws HiveException {
}
//處理函數的輸入並且輸出結果的過程
@Override
public void process(Object[] args) throws HiveException {
String input = args[0].toString();
input = input.replace("\"", "");
String[] result = input.split(" ");
//如果解析錯誤或失敗,則返回三個欄位內容都是"--"
if(result.length != 3){
result[0] = "--";
result[1] = "--";
result[2] = "--";
}
forward(result);
}
}
依照上面的步驟,匯出jar包,上傳到Linux伺服器上。在此不再贅述,其實是攢著另一種上傳檔案的方式,下次教給大家。
Step 1: add jar “jar-path”
略
Step 2: create function requestparse as ‘包名+類名’
Step 3: 使用該函數
對比我們之前置入的資料
UDAF(user-defined aggregation functions)
“小”需求:
求出最大的流量值
要點:
1.繼承自”org.apache.hadoop.hive.ql.exec.UDAF”;
2.自訂的內部類要實現介面”org.apache.hadoop.hive.ql.exec.UDAFEvaluator”;
3.要實現iterate()、terminatePartial()、merge()、terminate()四個方法。
*JAVA代碼
package com.hadoop.hivetest.udf;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.io.IntWritable;
@SuppressWarnings("deprecation")
public class MaxFlowUDAF extends UDAF {
public static class MaxNumberUDAFEvaluator implements UDAFEvaluator{
private IntWritable result;
public void init() {
result = null;
}
//彙總的多行中每行的被彙總的值都會被調用interate方法,所以這個方法裡面我們來定義彙總規則
public boolean iterate(IntWritable value){
if(value == null){
return false;
}
if(result == null){
result = new IntWritable(value.get());
}else{
//需求是求出流量最大值,在這裡進行流量的比較,將最大值放入result
result.set(Math.max(result.get(), value.get()));
}
return true;
}
//hive需要部分彙總結果時會調用該方法,返回當前的result作為hive取部分彙總值得結果
public IntWritable terminatePartial(){
return result;
}
//彙總值,新行未被處理的值會調用merge加入彙總,這裡直接調用上面定義的彙總規則方法iterate
public boolean merge(IntWritable other){
return iterate(other);
}
//hive需要最後總彙總結果時調用的方法,返回彙總的最終結果
public IntWritable terminate(){
return result;
}
}
}
匯出jar包,上傳到Linux伺服器…
Step 1: add jar ‘jar-path’
略
Step 2: create function maxflow as ‘包名+類名’
Step 3: 使用該函數
於是此時,hive便會將sql語句轉換為mapreduce任務去執行了。
當我們建立函數之後,得出的結果卻不是想要的結果的時候,我們將Java代碼修改之後,重新打了包上傳過來,也重新加到了hive的classpath中,但是新建立出來的函數得出的結果跟修改之前的一樣。這個因為新修改過後的類名與之前的類名重複了,在當前session中會優先以之前的來建立函數。此時有兩種辦法解決,一是斷開當前的串連,重新使用beeline用戶端登陸一次,還有就是將修改後的Java類改一個名稱,重新匯入,使用新的Java類來建立函數。
當然,這些才都只是 UDF 的小皮毛,我們可以發現,通過自訂函數,我們可以省去寫很多sql,並且通過使用api,我們可以更隨意的操作資料庫裡的欄位,實現多種計算和統計。
Hive編程指南 PDF 中文高清版 https://www.bkjia.com/Linux/2015-01/111837.htm
基於Hadoop叢集的Hive安裝 https://www.bkjia.com/Linux/2013-07/87952.htm
Hive內表和外表的區別 https://www.bkjia.com/Linux/2013-07/87313.htm
Hadoop + Hive + Map +reduce 叢集安裝部署 https://www.bkjia.com/Linux/2013-07/86959.htm
Hive本地獨立模式安裝 https://www.bkjia.com/Linux/2013-06/86104.htm
Hive學習之WordCount單詞統計 https://www.bkjia.com/Linux/2013-04/82874.htm
Hive運行架構及配置部署 https://www.bkjia.com/Linux/2014-08/105508.htm
Hive 2.1.1安裝配置詳解 https://www.bkjia.com/Linux/2017-04/143053.htm
Hive安裝及與HBase的整合 https://www.bkjia.com/Linux/2016-12/138721.htm
Hive 的詳細介紹:請點這裡
Hive 的:請點這裡
本文永久更新連結地址:https://www.bkjia.com/Linux/2018-03/151443.htm