採用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 UDFException
SQL中每一條記錄都會對應調用一次
process
,process
的參數為SQL語句中指定的UDTF輸入參數。輸入參數以Object[]
的形式傳入,輸出結果通過forward
函數輸出。您需要在process
函數內自行調用forward
,以決定輸出資料。說明當未使用
process
和close方法觸發forward
調用時,可能會導致資料丟失,請務必謹慎使用,以避免出現此情況。例如:通過後台線程執行了forward
調用,此時一定要確保process
方法在forward
調用結束後再結束,否則可能導致資料丟失。public void close() throws UDFException
UDTF的結束方法。只會被調用一次,即在處理完最後一條記錄之後被調用。
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。
說明運行參數可參照圖示資料填寫。
將建立的UDTF打包為JAR包,上傳至MaxCompute專案並註冊函數。例如函數名稱為
user_udtf
。更多打包操作,請參見操作步驟。
在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使用樣本。