您好,登錄后才能下訂單哦!
這篇文章主要介紹了hive中l(wèi)ateral view怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Lateral view與UDTF函數(shù)一起使用,UDTF對每個輸入行產(chǎn)生0或者多個輸出行。Lateral view首先在基表的每個輸入行應(yīng)用UDTF,然后連接結(jié)果輸出行與輸入行組成擁有指定表別名的虛擬表。
explain SELECT id, sq,myCol from window_test_table LATERAL VIEW explode(split(sq,',')) myTab as myCol;
這個sql 經(jīng)歷了兩條線:
ts(TableScan)-->lvf(Lateral View Forward)-->sel(Select)-->lvj(Lateral View Join)-->sel(Select) ts(TableScan)-->lvf(Lateral View Forward)-->sel(Select)-->udtf-->lvj(Lateral View Join)-->sel(Select)
不多說,常規(guī)讀表操作
@Override public void process(Object row, int tag) throws HiveException { forward(row, inputObjInspectors[tag]); }
幾乎什么都沒做,數(shù)據(jù)怎么來的,還怎么送出去。
篩選出你需要的非explode的列:id,sq
篩選出explode的列:split(sq, ',')
@Override public void process(Object row, int tag) throws HiveException { StructObjectInspector soi = (StructObjectInspector) inputObjInspectors[tag]; List<? extends StructField> fields = soi.getAllStructFieldRefs(); //從row里解出字段 for (int i = 0; i < fields.size(); i++) { objToSendToUDTF[i] = soi.getStructFieldData(row, fields.get(i)); } //真正處理數(shù)據(jù)的是 genericUDTF的某個實現(xiàn)類,比如,explode,那就是GenericUDTFExplode.java 的process genericUDTF.process(objToSendToUDTF); //這里判斷一下有沒有outer關(guān)鍵字。這里真的真的真的是,可能用了很久了,還不知道udtf還有個outer 關(guān)鍵字 if (conf.isOuterLV() && collector.getCounter() == 0) { //思考一下這一步是干嘛? collector.collect(outerObj); } collector.reset(); }
GenericUDTFExplode.java就相當(dāng)容易理解了,畢竟我們自己寫udtf時,也是這么做的:
/** * GenericUDTFExplode. * */ @Description(name = "explode", value = "_FUNC_(a) - separates the elements of array a into multiple rows," + " or the elements of a map into multiple rows and columns ") public class GenericUDTFExplode extends GenericUDTF { .... @Override //主要處理數(shù)據(jù)的方法 public void process(Object[] o) throws HiveException { switch (inputOI.getCategory()) { case LIST: //處理list ListObjectInspector listOI = (ListObjectInspector)inputOI; List<?> list = listOI.getList(o[0]); if (list == null) { return; //當(dāng)數(shù)組里沒有值時,不發(fā)送數(shù)據(jù) } for (Object r : list) { forwardListObj[0] = r; forward(forwardListObj); } break; case MAP: //處理map MapObjectInspector mapOI = (MapObjectInspector)inputOI; Map<?,?> map = mapOI.getMap(o[0]); if (map == null) { return; } for (Entry<?,?> r : map.entrySet()) { forwardMapObj[0] = r.getKey(); forwardMapObj[1] = r.getValue(); forward(forwardMapObj); } break; default: throw new TaskExecutionException("explode() can only operate on an array or a map"); } } .... }
當(dāng)UDTF不產(chǎn)生任何行時,比如explode()函數(shù)的輸入列為空,LATERALVIEW就不會生成任何輸出行。在這種情況下原有行永遠(yuǎn)不會出現(xiàn)在結(jié)果中。OUTRE可被用于阻止這種情況,輸出行中來自UDTF的列將被設(shè)置為NULL。
例如:
實際上從代碼里,也能夠看到:
UDTF會借助UDTFCollector為其展開的結(jié)果計數(shù),并forward:
@Override public void collect(Object input) throws HiveException { op.forwardUDTFOutput(input); counter++; }
如果沒有展開結(jié)果,counter就為0。 這樣,進(jìn)入outer之后,會把之前建好的沒有內(nèi)容的outerObj給forward到下個 算子LateralViewJoinOperator
@Override public void process(Object row, int tag) throws HiveException { StructObjectInspector soi = (StructObjectInspector) inputObjInspectors[tag]; //標(biāo)識是左側(cè)select過來的 if (tag == SELECT_TAG) { selectObjs.clear(); selectObjs.addAll(soi.getStructFieldsDataAsList(row)); } else if (tag == UDTF_TAG) { //代表是右側(cè)udtf過來的 acc.clear(); acc.addAll(selectObjs); acc.addAll(soi.getStructFieldsDataAsList(row)); //合并數(shù)據(jù) forward(acc, outputObjInspector); } else { throw new HiveException("Invalid tag"); } }
LateralViewJoinOperator處理邏輯也是很簡單明了,這里的join也是簡單的List.addAll
Lateral view explode 會產(chǎn)生shuffle嗎?
當(dāng)然不會,毋庸置疑! 其實一開始看執(zhí)行計劃就會發(fā)現(xiàn),沒有reduce任務(wù)呀~~
這里的Join代表的是兩份數(shù)據(jù)聯(lián)接到一起的意思,并不是真正的意義上的join。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“hive中l(wèi)ateral view怎么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。