採用Java語言編寫UDTF函數可有效處理複雜資料處理任務並自訂邏輯,並且通過合理利用Java語言的特性,能更好地滿足特定的資料處理需求,提升開發效率和處理效能。本文將介紹UDTF函數的代碼結構、使用說明和樣本。
UDTF代碼結構
您可以通過IntelliJ IDEA(Maven)或MaxCompute Studio工具使用Java語言編寫UDTF代碼,代碼中需要包含如下資訊:
-
Java包(Package):可選。
您可以將定義的Java類打包,為後續尋找和使用類提供方便。
-
繼承UDTF類:必選。
必須攜帶的UDTF類為
com.aliyun.odps.udf.UDTF、com.aliyun.odps.udf.annotation.Resolve(對應@Resolve註解)和com.aliyun.odps.udf.UDFException(對應實現Java類的方法)。當您需要使用其他UDTF類或者需要用到複雜資料類型時,請根據MaxCompute UDF概述添加需要的類。 -
自訂Java類:必選。
UDTF代碼的組織單位,定義了實現業務需求的變數及方法。
-
@Resolve註解:必選。格式為
@Resolve(<signature>)。signature為函數簽名,用於定義函數的輸入參數和傳回值的資料類型。UDTF無法通過反射分析擷取函數簽名,只能通過@Resolve註解方式擷取函數簽名,例如@Resolve("smallint->varchar(10)")。更多@Resolve註解資訊,請參見@Resolve註解。 -
實現Java類的方法:必選。
Java類實現包含如下4個方法,您可以根據實際需要進行選擇。
介面定義
描述
public void setup(ExecutionContext ctx) throws UDFException初始化方法,在UDTF處理輸入的資料前,MaxCompute會調用使用者自訂的初始化行為。在每個Worker內
setup會被先調用一次。public void process(Object[] args) throws UDFExceptionSQL中每一條記錄都會對應調用一次
process,process的參數為SQL語句中指定的UDTF輸入參數。輸入參數以Object[]的形式傳入,輸出結果通過forward函數輸出。您需要在process函數內自行調用forward,以決定輸出資料。說明當未使用
process和close方法觸發forward調用時,可能會導致資料丟失,請務必謹慎使用,以避免出現此情況。例如:通過後台線程執行了forward調用,此時一定要確保process方法在forward調用結束後再結束,否則可能導致資料丟失。public void close() throws UDFExceptionUDTF的結束方法。只會被調用一次,即在處理完最後一條記錄之後被調用。
public void forward(Object …o) throws UDFException調用
forward方法輸出資料,每調用一次forward代表輸出一條記錄。在SQL查詢語句中調用UDTF時,可以通過as子句將forward輸出的結果進行重新命名。編寫Java UDTF時可以使用Java Type或Java Writable Type,MaxCompute專案支援處理的資料類型與Java資料類型的詳細映射關係,請參見資料類型。
UDTF程式碼範例如下。
//將定義的Java類組織在org.alidata.odps.udtf.examples包中。
package org.alidata.odps.udtf.examples;
//繼承UDTF類。
import com.aliyun.odps.udf.UDTF;
import com.aliyun.odps.udf.UDTFCollector;
import com.aliyun.odps.udf.annotation.Resolve;
import com.aliyun.odps.udf.UDFException;
//自訂Java類。
//@Resolve註解。
@Resolve("string,bigint->string,bigint")
public class MyUDTF extends UDTF {
//實現Java類的方法。
@Override
public void process(Object[] args) throws UDFException {
String a = (String) args[0];
Long b = (Long) args[1];
for (String t: a.split("\\s+")) {
forward(t, b);
}
}
}
使用限制
不支援通過自訂函數訪問外網。如果您需要通過自訂函數訪問外網,請根據業務情況填寫並提交表單,MaxCompute支援人員團隊會及時聯絡您完成網路開通操作。表單填寫指導,請參見網路開通流程。
在
select語句中使用UDTF時,不允許存在其他列或運算式。錯誤樣本如下。--查詢語句中同時攜帶了UDTF和其他列。 select value, user_udtf(key) as mycol ...UDTF不能嵌套使用。錯誤樣本如下。
--user_udtf1嵌套了user_udtf2,不允許嵌套。 select user_udtf1(user_udtf2(key)) as mycol...;不支援在同一個
select子句中與group by、distribute by、sort by聯用。錯誤樣本如下。--UDTF不能與group by聯用。 select user_udtf(key) as mycol ... group by mycol;
注意事項
在編寫Java UDTF時,您需要注意:
-
不同UDTF JAR包中不建議存在類名相同但實現邏輯不一樣的類。例如UDTF1、UDTF2分別對應資源JAR包udtf1.jar、udtf2.jar,兩個JAR包裡都包含名稱為
com.aliyun.UserFunction.class的類但實現邏輯不一樣,當同一條SQL語句中同時調用UDTF1和UDTF2時,MaxCompute會隨機載入其中一個類,此時會導致UDTF執行結果不符合預期甚至編譯失敗。 -
Java UDTF中輸入或傳回值的資料類型是對象,資料類型首字母必須大寫,例如String。
-
SQL中的NULL值通過Java中的NULL表示。Java Primitive Type無法表示SQL中的NULL值,不允許使用。
@Resolve註解
@Resolve註解格式如下。
@Resolve(<signature>)
signature為函數簽名字串,用於標識輸入參數和傳回值的資料類型。執行UDTF時,UDTF函數的輸入參數和傳回值類型要與函數簽名指定的類型一致。查詢語義解析階段會檢查不符合函數簽名定義的用法,檢查到類型不符時會報錯。具體格式如下。
'arg_type_list -> type_list'
其中:
-
type_list:表示傳回值的資料類型。UDTF可以返回多列。支援的資料類型為:BIGINT、STRING、DOUBLE、BOOLEAN、DATETIME、DECIMAL、FLOAT、BINARY、DATE、DECIMAL(precision,scale)、複雜資料類型(ARRAY、MAP、STRUCT)或複雜資料類型嵌套。 -
arg_type_list:表示輸入參數的資料類型。輸入參數可以為多個,用英文逗號(,)分隔。支援的資料類型為BIGINT、STRING、DOUBLE、BOOLEAN、DATETIME、DECIMAL、FLOAT、BINARY、DATE、DECIMAL(precision,scale)、CHAR、VARCHAR、複雜資料類型(ARRAY、MAP、STRUCT)或複雜資料類型嵌套。arg_type_list還支援星號(*)或為空白(''):-
當
arg_type_list為星號(*)時,表示輸入參數為任意個數。 -
當
arg_type_list為空白('')時,表示無輸入參數。
更多Resolve註解文法擴充詳情,請參見UDAF和UDTF動態參數說明。
-
合法@Resolve註解樣本如下。
|
@Resolve註解樣本 |
說明 |
|
|
輸入參數類型為BIGINT、BOOLEAN,傳回值類型為STRING、DATETIME。 |
|
|
輸入任意個參數,傳回值類型為STRING、DATETIME。 |
|
|
無輸入參數,傳回值類型為DOUBLE、BIGINT、STRING。 |
|
|
輸入參數類型為ARRAY、STRUCT、MAP,傳回值類型為MAP、STRUCT。 |
資料類型
在MaxCompute中不同資料類型版本支援的資料類型不同。從MaxCompute 2.0版本開始,擴充了更多的新資料類型,同時還支援ARRAY、MAP、STRUCT等複雜類型。更多MaxCompute資料類型版本資訊,請參見資料類型版本說明。
為確保編寫Java UDTF過程中使用的資料類型與MaxCompute支援的資料類型保持一致,您需要關注二者間的資料類型映射關係。具體映射關係如下。
|
MaxCompute Type |
Java Type |
Java Writable Type |
|
TINYINT |
java.lang.Byte |
ByteWritable |
|
SMALLINT |
java.lang.Short |
ShortWritable |
|
INT |
java.lang.Integer |
IntWritable |
|
BIGINT |
java.lang.Long |
LongWritable |
|
FLOAT |
java.lang.Float |
FloatWritable |
|
DOUBLE |
java.lang.Double |
DoubleWritable |
|
DECIMAL |
java.math.BigDecimal |
BigDecimalWritable |
|
BOOLEAN |
java.lang.Boolean |
BooleanWritable |
|
STRING |
java.lang.String |
Text |
|
VARCHAR |
com.aliyun.odps.data.Varchar |
VarcharWritable |
|
BINARY |
com.aliyun.odps.data.Binary |
BytesWritable |
|
DATE |
java.sql.Date |
DateWritable |
|
DATETIME |
java.util.Date |
DatetimeWritable |
|
TIMESTAMP |
java.sql.Timestamp |
TimestampWritable |
|
INTERVAL_YEAR_MONTH |
不涉及 |
IntervalYearMonthWritable |
|
INTERVAL_DAY_TIME |
不涉及 |
IntervalDayTimeWritable |
|
ARRAY |
java.util.List |
不涉及 |
|
MAP |
java.util.Map |
不涉及 |
|
STRUCT |
com.aliyun.odps.data.Struct |
不涉及 |
當MaxCompute專案採用MaxCompute 2.0資料類型版本時,UDTF的輸入或傳回值才可以使用Java Writable Type。
使用說明
按照開發流程,完成Java UDTF開發後,您即可通過MaxCompute SQL調用Java UDTF。調用方法如下:
在歸屬MaxCompute專案中使用自訂函數:使用方法與內建函數類似,您可以參照內建函數的使用方法使用自訂函數。
跨專案使用自訂函數:即在專案A中使用專案B的自訂函數,跨專案分享語句樣本:
select B:udf_in_other_project(arg0, arg1) as res from table_t;。更多跨專案分享資訊,請參見基於Package跨專案訪問資源。
使用MaxCompute Studio完整開發及調用Java UDTF的操作,請參見使用樣本。
使用樣本
以通過MaxCompute Studio開發UDTF為例,開發並調用Java UDTF的操作步驟如下:
-
準備工作。
使用MaxCompute Studio開發調試UDF時,您需要先安裝MaxCompute Studio並串連MaxCompute專案,做好UDF開發前準備工作。操作詳情請參見:
-
編寫UDTF代碼。
-
在Project地區,按右鍵Module的源碼目錄(即),選擇。

-
在Create new MaxCompute java class對話方塊,單擊UDTF並填寫Name後,按Enter鍵。例如Java Class名稱為MyUDTF。
Name為建立的MaxCompute Java Class名稱。如果還沒有建立Package,在此處填寫packagename.classname,會自動產生Package。
-
在代碼編寫地區寫入如下代碼。UDTF程式碼範例如下。
package org.alidata.odps.udtf.examples; import com.aliyun.odps.udf.UDTF; import com.aliyun.odps.udf.UDTFCollector; import com.aliyun.odps.udf.annotation.Resolve; import com.aliyun.odps.udf.UDFException; // TODO define input and output types, e.g., "string,string->string,bigint". @Resolve("string,bigint->string,bigint") public class MyUDTF extends UDTF { @Override public void process(Object[] args) throws UDFException { String a = (String) args[0]; Long b = (Long) args[1]; for (String t: a.split("\\s+")) { forward(t, b); } } }
-
-
在本地運行調試UDTF,確保代碼可以運行成功。
更多調試操作,請參見通過本地運行調試UDF。
按右鍵左側專案樹中的 MyUDTF 檔案,選擇 Run 'MyUDTF.main()'。在彈出的 Run/Debug Configurations 對話方塊中,設定 MaxCompute project 為
local,MaxCompute table 為wc_in2,Table partition 為p2=1,p1=2,Table columns 為colc,colb,Download Record limit 為100,Data Column Separator 為|,然後單擊 OK。說明運行參數可參照圖示資料填寫。
-
將建立的UDTF打包為JAR包,上傳至MaxCompute專案並註冊函數。例如函數名稱為
user_udtf。更多打包操作,請參見操作步驟。
在IntelliJ IDEA專案樹中按右鍵UDTF的Java檔案(如MyUDTF),選擇Deploy to server...。在彈出的Package a jar, submit resource and register function對話方塊中,選擇目標MaxCompute project,確認Resource file路徑,設定Main class為對應的UDTF類(如
org.alidata.odps.udtf.examples.MyUDTF),填寫Function name為user_udtf,勾選Force update if already exists,單擊OK完成部署。 -
在MaxCompute Studio的左側導覽列,單擊Project Explorer,在目標MaxCompute專案上單擊右鍵,啟動MaxCompute用戶端,並執行SQL命令調用新建立的UDTF。
假設待查詢目標表my_table的資料結構如下。
+------------+------------+ | col0 | col1 | +------------+------------+ | A B | 1 | | C D | 2 | +------------+------------+執行如下SQL命令調用UDTF。
select user_udtf(col0, col1) as (c0, c1) from my_table;返回結果如下。
+----+------------+ | c0 | c1 | +----+------------+ | A | 1 | | B | 1 | | C | 2 | | D | 2 | +----+------------+
相關文檔
關於Java UDTF的使用樣本詳情,請參見Java UDTF使用樣本。