您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”這篇文章吧。
一、 控制hive任務(wù)中的map數(shù):
1. 通常情況下,作業(yè)會通過input的目錄產(chǎn)生一個或者多個map任務(wù)。
主要的決定因素有: input的文件總個數(shù),input的文件大小,集群設(shè)置的文件塊大小(目前為128M, 可在hive中通過set dfs.block.size;命令查看到,該參數(shù)不能自定義修改);
2. 舉例:
a) 假設(shè)input目錄下有1個文件a,大小為780M,那么hadoop會將該文件a分隔成7個塊(6個128m的塊和1個12m的塊),從而產(chǎn)生7個map數(shù)
b) 假設(shè)input目錄下有3個文件a,b,c,大小分別為10m,20m,130m,那么hadoop會分隔成4個塊(10m,20m,128m,2m),從而產(chǎn)生4個map數(shù)
即,如果文件大于塊大小(128m),那么會拆分,如果小于塊大小,則把該文件當成一個塊。
3. 是不是map數(shù)越多越好?
答案是否定的。如果一個任務(wù)有很多小文件(遠遠小于塊大小128m),則每個小文件也會被當做一個塊,用一個map任務(wù)來完成,
而一個map任務(wù)啟動和初始化的時間遠遠大于邏輯處理的時間,就會造成很大的資源浪費。
而且,同時可執(zhí)行的map數(shù)是受限的。
4. 是不是保證每個map處理接近128m的文件塊,就高枕無憂了?
答案也是不一定。比如有一個127m的文件,正常會用一個map去完成,但這個文件只有一個或者兩個小字段,卻有幾千萬的記錄,
如果map處理的邏輯比較復(fù)雜,用一個map任務(wù)去做,肯定也比較耗時。
針對上面的問題3和4,我們需要采取兩種方式來解決:即減少map數(shù)和增加map數(shù);
如何合并小文件,減少map數(shù)?
假設(shè)一個SQL任務(wù):
Select count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04’;
該任務(wù)的inputdir /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04
共有194個文件,其中很多是遠遠小于128m的小文件,總大小9G,正常執(zhí)行會用194個map任務(wù)。
Map總共消耗的計算資源: SLOTS_MILLIS_MAPS= 623,020
我通過以下方法來在map執(zhí)行前合并小文件,減少map數(shù):
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
再執(zhí)行上面的語句,用了74個map任務(wù),map消耗的計算資源:SLOTS_MILLIS_MAPS= 333,500
對于這個簡單SQL任務(wù),執(zhí)行時間上可能差不多,但節(jié)省了一半的計算資源。
大概解釋一下,100000000表示100M, set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;這個參數(shù)表示執(zhí)行前進行小文件合并,
前面三個參數(shù)確定合并文件塊的大小,大于文件塊大小128m的,按照128m來分隔,小于128m,大于100m的,按照100m來分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),
進行合并,最終生成了74個塊。
如何適當?shù)脑黾觤ap數(shù)?
當input的文件都很大,任務(wù)邏輯復(fù)雜,map執(zhí)行非常慢的時候,可以考慮增加Map數(shù),來使得每個map處理的數(shù)據(jù)量減少,從而提高任務(wù)的執(zhí)行效率。
假設(shè)有這樣一個任務(wù):
Select data_desc,
count(1),
count(distinct id),
sum(case when …),
sum(case when ...),
sum(…)
from a group by data_desc
如果表a只有一個文件,大小為120M,但包含幾千萬的記錄,如果用1個map去完成這個任務(wù),肯定是比較耗時的,這種情況下,我們要考慮將這一個文件合理的拆分成多個,
這樣就可以用多個map任務(wù)去完成。
set mapred.reduce.tasks=10;
create table a_1 as
select * from a
distribute by rand(123);
這樣會將a表的記錄,隨機的分散到包含10個文件的a_1表中,再用a_1代替上面sql中的a表,則會用10個map任務(wù)去完成。
每個map任務(wù)處理大于12M(幾百萬記錄)的數(shù)據(jù),效率肯定會好很多。
看上去,貌似這兩種有些矛盾,一個是要合并小文件,一個是要把大文件拆成小文件,這點正是重點需要關(guān)注的地方,
根據(jù)實際情況,控制map數(shù)量需要遵循兩個原則:使大數(shù)據(jù)量利用合適的map數(shù);使單個map任務(wù)處理合適的數(shù)據(jù)量;
二、 控制hive任務(wù)的reduce數(shù):
1. Hive自己如何確定reduce數(shù):
reduce個數(shù)的設(shè)定極大影響任務(wù)執(zhí)行效率,不指定reduce個數(shù)的情況下,Hive會猜測確定一個reduce個數(shù),基于以下兩個設(shè)定:
hive.exec.reducers.bytes.per.reducer(每個reduce任務(wù)處理的數(shù)據(jù)量,默認為1000^3=1G)
hive.exec.reducers.max(每個任務(wù)最大的reduce數(shù),默認為999)
計算reducer數(shù)的公式很簡單N=min(參數(shù)2,總輸入數(shù)據(jù)量/參數(shù)1)
即,如果reduce的輸入(map的輸出)總大小不超過1G,那么只會有一個reduce任務(wù);
如:select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt;
/group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04 總大小為9G多,因此這句有10個reduce
2. 調(diào)整reduce個數(shù)方法一:
調(diào)整hive.exec.reducers.bytes.per.reducer參數(shù)的值;
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt; 這次有20個reduce
3. 調(diào)整reduce個數(shù)方法二;
set mapred.reduce.tasks = 15;
select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt;這次有15個reduce
4. reduce個數(shù)并不是越多越好;
同map一樣,啟動和初始化reduce也會消耗時間和資源;
另外,有多少個reduce,就會有多少個輸出文件,如果生成了很多個小文件,那么如果這些小文件作為下一個任務(wù)的輸入,則也會出現(xiàn)小文件過多的問題;
5. 什么情況下只有一個reduce;
很多時候你會發(fā)現(xiàn)任務(wù)中不管數(shù)據(jù)量多大,不管你有沒有設(shè)置調(diào)整reduce個數(shù)的參數(shù),任務(wù)中一直都只有一個reduce任務(wù);
其實只有一個reduce任務(wù)的情況,除了數(shù)據(jù)量小于hive.exec.reducers.bytes.per.reducer參數(shù)值的情況外,還有以下原因:
a) 沒有g(shù)roup by的匯總,比如把select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt; 寫成 select count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04';
這點非常常見,希望大家盡量改寫。
b) 用了Order by
c) 有笛卡爾積
通常這些情況下,除了找辦法來變通和避免,我暫時沒有什么好的辦法,因為這些操作都是全局的,所以hadoop不得不用一個reduce去完成;
同樣的,在設(shè)置reduce個數(shù)的時候也需要考慮這兩個原則:使大數(shù)據(jù)量利用合適的reduce數(shù);使單個reduce任務(wù)處理合適的數(shù)據(jù)量。
以上是“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。