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