雖然Hive已經提供了很多內置的函數,比如count()、sum(),但是還是不能滿足用戶的需求,因此提供了自定義函數供用戶自己開發函數來滿足自己的需求。
一、自定義函數分類
- UDF(User-Defined-Function)用戶自定義函數,輸入一個數據然後產生一個數據;
- UDAF(User-Defined Aggregation Function)用戶自定義聚合函數,多個輸入數據然後產生一個輸出參數;
- UDTF(User-Defined Table-generating Function)用戶自定義表生成函數,輸入一行數據生成N行數據
接下來,我們將編寫自己的UDF,實現通過一個人的出生日期,計算其所屬的星座。
二、自定義函數流程
要想在Hive中完成自定義函數的操作,要按照如下的流程進行操作:
1、自定義Java類並繼承org.apache.hadoop.hive.ql.exec.UDF;
2、覆寫evaluate函數,evaluate函數支持重載;
3、把程序打包放到hive所在服務器;
4、進入hive客戶端,添加jar包;
5、創建關聯到Java類的Hive函數;
6、Hive命令行中執行查詢語句:select id, 方法名(name) from 表名——得出自定義函數輸出的結果。
三、自定義函數實現
1、創建java類
新建java工程,導入項目依賴包hive-exec-x.x.x.jar,創建類UDFDemo如下:
package cn.hust.book.bigdata;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
@Description(name="UDFDemo", value="_FUNC_(date)-from the input date string"+"or separate month and day arguments,returns the sign of the UDFDemo",
extended ="Example :\n"+"> SELECT _FUNC_(data_string) from src;\n"+ ">SELECT _FUNC_(mouth,day0) FORM src;")
public class UDFDemo extends UDF {
private SimpleDateFormat df;
public UDFDemo(){
df= new SimpleDateFormat("yyyy-MM-dd");
}
public String evaluate(String date_str) throws Exception{
int month;
int day;
try{
java.util.Date bday = df.parse(date_str);
Calendar cal = Calendar.getInstance();
cal.setTime(bday);
month = cal.get(Calendar.MONTH)+1;
day = cal.get(Calendar.DAY_OF_MONTH);
}catch (Exception e) {
return null;
}
if(month==1){
if(day<20){
return "魔蠍座";
}else{
return "水瓶座";
}
}
if(month==2){
if(day<19){
return "水瓶座";
}else{
return "雙魚座";
}
}
if(month==3){
if(day<21){
return "雙魚座";
}else{
return "白羊座";
}
}
if(month==4){
if(day<20){
return "白羊座";
}else{
return "金牛座";
}
}
if(month==5){
if(day<21){
return "金牛座";
}else{
return "雙子座";
}
}
if(month==6){
if(day<22){
return "雙子座";
}else{
return "巨蟹座";
}
}
if(month==7){
if(day<23){
return "巨蟹座";
}else{
return "獅子座";
}
}
if(month==8){
if(day<23){
return "獅子座";
}else{
return "處女座";
}
}
if(month==9){
if(day<23){
return "處女座";
}else{
return "天秤座";
}
}
if(month==10){
if(day<24){
return "天秤座";
}else{
return "天蠍座";
}
}
if(month==11){
if(day<23){
return "天蠍座";
}else{
return "射手座";
}
}
if(month==12){
if(day<22){
return "射手座";
}else{
return "摩羯座";
}
}
return null;
}
/*
* 測試
*/
public static void main(String[] args) throws Exception{
UDFDemo demo =new UDFDemo();
String date_str = "2009-04-15";
System.out.println("result:"+demo.evaluate(date_str));
}
}
編寫一個UDF,關鍵在於自定義Java類需要繼承UDF類並實現evaluate()函數。因爲在hive客戶端執行查詢時,查詢中每處應用到這個函數的地方都會對這個類進行實例化。對於每行輸入都會調用evaluate()函數,evaluate()函數處理後的值會返回給hive。
2、項目打包
將項目在eclipes中打包爲jar包並命名爲HiveUDF.jar,打包後上傳到服務器指定目錄,此處我們選擇/home/hadoop/hive-test目錄,如圖所示:
3、加載樣本數據集
進入到hive客戶端,創建數據表:
- hive> CREATE TABLE IF NOT EXISTS userinfo(
- >name STRING , //姓名
- >bday STRING , //出生日期
- )
- > ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
將樣本數據集加載到userinfo表中:
- hive> LOAD DATA LOCAL INPATH '樣本數據集地址'
- > INTO TABLE userinfo;
我們的樣本數據集內容如下(地址:/home/hadoop/hive-test/bday.txt):
4、添加jar包
在hive客戶端,將HiveUDF.jar文件加載到類路徑:
- hive> ADD JAR /home/hadoop/hive-test/HiveUDF.jar;
5、創建關聯到Java類的hive函數
通過CREATE FUNCTION語句定義好使用這個java類的函數:
- hive> CREATE TEMPORARY FUNCTION HiveUDF
- > AS 'cn.hust.book.bigdata.UDFDemo'; //cn.hust.book.bigdata.UDFDemo對應java程序包名+類名
6、執行查詢
到目前爲止,這個判斷星座的UDF可以像其他函數一樣使用了,首先,我們看一下HiveUDF()函數的描述:
- hive> DESCRIBE FUNCTION HiveUDF;
接下來,查詢樣本數據集中人員出生日期對應的星座:
- hive> SELECT name,bday,HiveUDF(bday) from userinfo;
當我們使用完自定義UDF後,可通過如下命令刪除此函數:
- hive> DROP TEMPORARY FUNCTION HiveUDF;
最後,附上源碼+依賴包+HiveUDF.jar下載地址:
鏈接:https://pan.baidu.com/s/17BrNv5HciFL9GW3QmY4fIA
密碼:xeal
杜海朋 2018.04.18