UDTF(User-Defined Table-Generating Functions) 用來解決 輸入一行輸出多行(On-to-many maping) 的需求。java
繼承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,實現initialize, process, close三個方法。apache
UDTF首先會調用initialize方法,此方法返回UDTF的返回行的信息(返回個數,類型)。api
初始化完成後,會調用process方法,真正的處理過程在process函數中,在process中,每一次forward()調用產生一行;若是產生多列能夠將多個列的值放在一個數組中,而後將該數組傳入到forward()函數。數組
最後close()方法調用,對須要清理的方法進行清理。ide
下面是我寫的一個用來切分」key:value;key:value;」這種字符串,返回結果爲key, value兩個字段。供參考:函數
import java.util.ArrayList; import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF; 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.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 ExplodeMap extends GenericUDTF{ @Override public void close() throws HiveException { // TODO Auto-generated method stub } @Override public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException { if (args.length != 1) { throw new UDFArgumentLengthException("ExplodeMap takes only one argument"); } if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) { throw new UDFArgumentException("ExplodeMap takes string as a parameter"); } ArrayList<String> fieldNames = new ArrayList<String>(); ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(); fieldNames.add("col1"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); fieldNames.add("col2"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs); } @Override public void process(Object[] args) throws HiveException { String input = args[0].toString(); String[] test = input.split(";"); for(int i=0; i<test.length; i++) { try { String[] result = test[i].split(":"); forward(result); } catch (Exception e) { continue; } } } }
UDTF有兩種使用方法,一種直接放到select後面,一種和lateral view一塊兒使用。oop
1:直接select中使用ui
select explode_map(properties) as (col1,col2) from src;
不能夠添加其餘字段使用.net
select a, explode_map(properties) as (col1,col2) from src
不能夠嵌套調用code
select explode_map(explode_map(properties)) from src
不能夠和group by/cluster by/distribute by/sort by一塊兒使用
select explode_map(properties) as (col1,col2) from src group by col1, col2
2:和lateral view一塊兒使用
select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable as col1, col2;
此方法更爲方便平常使用。執行過程至關於單獨執行了兩次抽取,而後union到一個表裏。
參考文檔
http://wiki.apache.org/hadoop/Hive/LanguageManual/UDF
http://wiki.apache.org/hadoop/Hive/DeveloperGuide/UDTF
http://www.slideshare.net/pauly1/userdefined-table-generating-functions