Hive性能優(yōu)化:
hive分配map和reduce數(shù)量
m,r數(shù)據(jù)量,對(duì)效率影響較大,因?yàn)樵趩?dòng)和初始化階段是很耗費(fèi)時(shí)間和資源的。
(1)控制mapper的數(shù)據(jù)量
通常情況下,作業(yè)會(huì)通過input的目錄產(chǎn)生一個(gè)或多個(gè)map任務(wù),
主要決定的因素有:input的文件總個(gè)數(shù),input的文件大小
Eg:
a) 假設(shè)input目錄下有1個(gè)文件a,大小為780M,那么hadoop會(huì)將該文件a分隔成7個(gè)塊(block為128M,6個(gè)128m的塊和1個(gè)12m的塊),從而產(chǎn)生7個(gè)map數(shù)
b) 假設(shè)input目錄下有3個(gè)文件a,b,c,大小分別為10m,20m,130m,那么hadoop會(huì)分隔成4個(gè)塊(10m,20m,128m,2m),從而產(chǎn)生4個(gè)map數(shù)
兩種方式控制map數(shù)量:
通過合并小文件來實(shí)現(xiàn)
合并小文件參數(shù)屬性:
(1)是否合并Map輸出文件:hive.merge.mapfiles=true(默認(rèn)值為真)
(2)是否合并Reduce 端輸出文件:hive.merge.mapredfiles=false(默認(rèn)值為假)
(3)合并文件的大小:hive.merge.size.per.task=25610001000(默認(rèn)值為256000000)
通過控制上一個(gè)job的reduce數(shù)量來控制
(2)控制reducer的數(shù)據(jù)量
? Reducer的個(gè)數(shù)極大的影響執(zhí)行效率,不指定reducer個(gè)數(shù)的情況下,hive分配reducer個(gè)數(shù)基于以下:
[if !supportLists](1)??????[endif]參數(shù)1:hive.exec.reducers.bytes.per.reducer(默認(rèn)為1G)
[if !supportLists](2)??????[endif]參數(shù)2 :hive.exec.reducers.max(默認(rèn)為999)
計(jì)算reducer數(shù)的公式
N=min(參數(shù)2,總輸入數(shù)據(jù)量/參數(shù)1)
或者直接指定reducer個(gè)數(shù):setmapred.reduce.tasks=13;?? //但是效果不是很好
???? Reducer個(gè)數(shù)不是越多越好,同map一樣,啟動(dòng)和初始化reduce也會(huì)消耗時(shí)間和資源;有多少個(gè)reduce就有多少個(gè)輸出文件
??????Reduce數(shù)過多:生成很多小文件,如果這些小文件作為下一個(gè)任務(wù)的輸入,則會(huì)出現(xiàn)小文件過多的問題
??????Reduce過少:影響執(zhí)行效率
???? 什么情況下只會(huì)有一個(gè)reduce:
???????很多時(shí)候會(huì)發(fā)現(xiàn),任務(wù)重不管數(shù)據(jù)量有多大,不管有沒有調(diào)整reduce的個(gè)數(shù),任務(wù)重一直都只有一個(gè)reduce
(1)? ? 數(shù)據(jù)量小于hive.exec.reducers.bytes.per.reducer參數(shù)值的情況外
(2)? ?沒有g(shù)roup by的匯總
(3)? ? 用了order by
2.關(guān)于join:
(1)將數(shù)據(jù)量少的表或者子查詢放在join的左邊,
原因:在join操作的reduce階段,位于join左邊的表的數(shù)據(jù)會(huì)被加載進(jìn)內(nèi)存,將數(shù)據(jù)量少的表放在左側(cè),可以有效減少內(nèi)存溢出的概率
注:如果多個(gè)join操作,且每個(gè)表參與多個(gè)join的字段相同,則將所有的join合并到一個(gè)mapperd程序中
Eg:
//在一個(gè)mapre程序中執(zhí)行join
SELECT a.val, b.val, c.val
FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)? ?
//在兩個(gè)mapred程序中執(zhí)行join
SELECT a.val, b.val, c.val
FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)??
Eg2中會(huì)在兩個(gè)mapper中執(zhí)行,是由于參與兩次join的表b的key不一致
(2) Map join的關(guān)鍵在于join操作中的某個(gè)表的數(shù)據(jù)量很小,join操作在map中完成,不再需要reduce
Eg:
SELECT /*+ MAPJOIN(b) */ a.key,? a.value
? FROM a join b on a.key =? b.key
注:mapjoin無法執(zhí)行a full/right outer join b 操作、
相關(guān)參數(shù):
hive.join.emit.interval= 1000
hive.mapjoin.size.key= 10000
hive.mapjoin.cache.numrows = 10000
???? 注:在進(jìn)行join操作的條件過濾的時(shí)候,應(yīng)該講過濾條件放在on關(guān)鍵詞里面,這樣可以提高效率
??????原因:join操作是在where操作之前執(zhí)行,所以在執(zhí)行join時(shí),where條件并不能起到減少join數(shù)據(jù)的作用
3.group by優(yōu)化
????? Map端聚合,首先在map端進(jìn)行初步的聚合,最后在reduce端得出最終結(jié)果。
??? 相關(guān)參數(shù):
(1)? hive.map.aggr = true? //是否在 Map 端進(jìn)行聚合,默認(rèn)為True
(2)? hive.groupby.mapaggr.checkinterval
= 100000 //在 Map 端進(jìn)行聚合操作的條目數(shù)目
?????數(shù)據(jù)傾斜的聚合優(yōu)化,對(duì)數(shù)據(jù)進(jìn)行聚合優(yōu)化,可以進(jìn)行參數(shù)設(shè)置:
???????hive.groupby.skewindata = true
當(dāng)此項(xiàng)設(shè)定為 true,生成的查詢計(jì)劃會(huì)有兩個(gè) MR Job。第一個(gè) MR Job 中,Map 的輸出結(jié)果集合會(huì)隨機(jī)分布到 Reduce 中,每個(gè) Reduce 做部分聚合操作,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key 有可能被分發(fā)到不同的 Reduce 中,從而達(dá)到負(fù)載均衡的目的;第二個(gè) MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照Group
? By Key 分布到 Reduce 中(這個(gè)過程可以保證相同的 Group
? By Key 被分布到同一個(gè) Reduce 中),最后完成最終的聚合操作。
4. 如何調(diào)整map數(shù)量
?通常有一下參數(shù)可以決定map的數(shù)量
set mapred.max.split.size=256000000;??????? --決定每個(gè)map處理的最大的文件大小,單位為B
set mapred.min.split.size.per.node=1;???????? --節(jié)點(diǎn)中可以處理的最小的文件大小
set mapred.min.split.size.per.rack=1;???????? --機(jī)架中可以處理的最小的文件大小
沒有辦法直接控制map的數(shù)量,只能通過以上參數(shù)的設(shè)置來控制map的分配數(shù)量
set mapred.max.split.size=1024000000;
setmapred.min.split.size.per.node=1024000000;
setmapred.min.split.size.per.rack=1024000000;
可以簡(jiǎn)單的理解為集群對(duì)一個(gè)表分區(qū)下面的文件進(jìn)行分發(fā)到各個(gè)節(jié)點(diǎn),之后根據(jù)mapred.max.split.size確認(rèn)要啟動(dòng)多少個(gè)map數(shù),邏輯如下?? a.假設(shè)有兩個(gè)文件大小分別為(256M,280M)被分配到節(jié)點(diǎn)A,那么會(huì)啟動(dòng)兩個(gè)map,剩余的文件大小為10MB和35MB因?yàn)槊總€(gè)大小都不足241MB會(huì)先做保留?? b.根據(jù)參數(shù)set
? mapred.min.split.size.per.node看剩余的大小情況并進(jìn)行合并,如果值為1,表示a中每個(gè)剩余文件都會(huì)自己起一個(gè)map,這里會(huì)起兩個(gè),如果設(shè)置為大于45*1024*1024則會(huì)合并成一個(gè)塊,并產(chǎn)生一個(gè)map?? 如果mapred.min.split.size.per.node為10*1024*1024,那么在這個(gè)節(jié)點(diǎn)上一共會(huì)有4個(gè)map,處理的大小為(245MB,245MB,10MB,10MB,10MB,10MB),余下9MB?? 如果mapred.min.split.size.per.node為45*1024*1024,那么會(huì)有三個(gè)map,處理的大小為(245MB,245MB,45MB)?? 實(shí)際中mapred.min.split.size.per.node無法準(zhǔn)確地設(shè)置成45*1024*1024,會(huì)有剩余并保留帶下一步進(jìn)行判斷處理?? c. 對(duì)b中余出來的文件與其它節(jié)點(diǎn)余出來的文件根據(jù)mapred.min.split.size.per.rack大小進(jìn)行判斷是否合并,對(duì)再次余出來的文件獨(dú)自產(chǎn)生一個(gè)map處理
重點(diǎn):注意各參數(shù)的設(shè)置大小,不要沖突,否則會(huì)異常,大小順序如下?
mapred.max.split.size <= mapred.min.split.size.per.node
<= mapred.min.split.size.per.rack?
調(diào)整reduce數(shù)量,不建議隨意設(shè)置reduce參數(shù),可能調(diào)整參數(shù)更好一點(diǎn)?
set hive.exec.reducers.bytes.per.reducer=1073741824