這篇文章主要為大家展示了“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”這篇文章吧。
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、成都做網(wǎng)站、豐鎮(zhèn)網(wǎng)絡(luò)推廣、成都小程序開(kāi)發(fā)、豐鎮(zhèn)網(wǎng)絡(luò)營(yíng)銷、豐鎮(zhèn)企業(yè)策劃、豐鎮(zhèn)品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供豐鎮(zhèn)建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com
一、 控制hive任務(wù)中的map數(shù):
1. 通常情況下,作業(yè)會(huì)通過(guò)input的目錄產(chǎn)生一個(gè)或者多個(gè)map任務(wù)。
主要的決定因素有: input的文件總個(gè)數(shù),input的文件大小,集群設(shè)置的文件塊大小(目前為128M, 可在hive中通過(guò)set dfs.block.size;命令查看到,該參數(shù)不能自定義修改);
2. 舉例:
a) 假設(shè)input目錄下有1個(gè)文件a,大小為780M,那么hadoop會(huì)將該文件a分隔成7個(gè)塊(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ù)
即,如果文件大于塊大小(128m),那么會(huì)拆分,如果小于塊大小,則把該文件當(dāng)成一個(gè)塊。
3. 是不是map數(shù)越多越好?
答案是否定的。如果一個(gè)任務(wù)有很多小文件(遠(yuǎn)遠(yuǎn)小于塊大小128m),則每個(gè)小文件也會(huì)被當(dāng)做一個(gè)塊,用一個(gè)map任務(wù)來(lái)完成,
而一個(gè)map任務(wù)啟動(dòng)和初始化的時(shí)間遠(yuǎn)遠(yuǎn)大于邏輯處理的時(shí)間,就會(huì)造成很大的資源浪費(fèi)。
而且,同時(shí)可執(zhí)行的map數(shù)是受限的。
4. 是不是保證每個(gè)map處理接近128m的文件塊,就高枕無(wú)憂了?
答案也是不一定。比如有一個(gè)127m的文件,正常會(huì)用一個(gè)map去完成,但這個(gè)文件只有一個(gè)或者兩個(gè)小字段,卻有幾千萬(wàn)的記錄,
如果map處理的邏輯比較復(fù)雜,用一個(gè)map任務(wù)去做,肯定也比較耗時(shí)。
針對(duì)上面的問(wèn)題3和4,我們需要采取兩種方式來(lái)解決:即減少map數(shù)和增加map數(shù);
如何合并小文件,減少map數(shù)?
假設(shè)一個(gè)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個(gè)文件,其中很多是遠(yuǎn)遠(yuǎn)小于128m的小文件,總大小9G,正常執(zhí)行會(huì)用194個(gè)map任務(wù)。
Map總共消耗的計(jì)算資源: SLOTS_MILLIS_MAPS= 623,020
我通過(guò)以下方法來(lái)在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í)行上面的語(yǔ)句,用了74個(gè)map任務(wù),map消耗的計(jì)算資源:SLOTS_MILLIS_MAPS= 333,500
對(duì)于這個(gè)簡(jiǎn)單SQL任務(wù),執(zhí)行時(shí)間上可能差不多,但節(jié)省了一半的計(jì)算資源。
大概解釋一下,100000000表示100M, set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;這個(gè)參數(shù)表示執(zhí)行前進(jìn)行小文件合并,
前面三個(gè)參數(shù)確定合并文件塊的大小,大于文件塊大小128m的,按照128m來(lái)分隔,小于128m,大于100m的,按照100m來(lái)分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),
進(jìn)行合并,最終生成了74個(gè)塊。
如何適當(dāng)?shù)脑黾觤ap數(shù)?
當(dāng)input的文件都很大,任務(wù)邏輯復(fù)雜,map執(zhí)行非常慢的時(shí)候,可以考慮增加Map數(shù),來(lái)使得每個(gè)map處理的數(shù)據(jù)量減少,從而提高任務(wù)的執(zhí)行效率。
假設(shè)有這樣一個(gè)任務(wù):
Select data_desc,
count(1),
count(distinct id),
sum(case when …),
sum(case when ...),
sum(…)
from a group by data_desc
如果表a只有一個(gè)文件,大小為120M,但包含幾千萬(wàn)的記錄,如果用1個(gè)map去完成這個(gè)任務(wù),肯定是比較耗時(shí)的,這種情況下,我們要考慮將這一個(gè)文件合理的拆分成多個(gè),
這樣就可以用多個(gè)map任務(wù)去完成。
set mapred.reduce.tasks=10;
create table a_1 as
select * from a
distribute by rand(123);
這樣會(huì)將a表的記錄,隨機(jī)的分散到包含10個(gè)文件的a_1表中,再用a_1代替上面sql中的a表,則會(huì)用10個(gè)map任務(wù)去完成。
每個(gè)map任務(wù)處理大于12M(幾百萬(wàn)記錄)的數(shù)據(jù),效率肯定會(huì)好很多。
看上去,貌似這兩種有些矛盾,一個(gè)是要合并小文件,一個(gè)是要把大文件拆成小文件,這點(diǎn)正是重點(diǎn)需要關(guān)注的地方,
根據(jù)實(shí)際情況,控制map數(shù)量需要遵循兩個(gè)原則:使大數(shù)據(jù)量利用合適的map數(shù);使單個(gè)map任務(wù)處理合適的數(shù)據(jù)量;
二、 控制hive任務(wù)的reduce數(shù):
1. Hive自己如何確定reduce數(shù):
reduce個(gè)數(shù)的設(shè)定極大影響任務(wù)執(zhí)行效率,不指定reduce個(gè)數(shù)的情況下,Hive會(huì)猜測(cè)確定一個(gè)reduce個(gè)數(shù),基于以下兩個(gè)設(shè)定:
hive.exec.reducers.bytes.per.reducer(每個(gè)reduce任務(wù)處理的數(shù)據(jù)量,默認(rèn)為1000^3=1G)
hive.exec.reducers.max(每個(gè)任務(wù)最大的reduce數(shù),默認(rèn)為999)
計(jì)算reducer數(shù)的公式很簡(jiǎn)單N=min(參數(shù)2,總輸入數(shù)據(jù)量/參數(shù)1)
即,如果reduce的輸入(map的輸出)總大小不超過(guò)1G,那么只會(huì)有一個(gè)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個(gè)reduce
2. 調(diào)整reduce個(gè)數(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個(gè)reduce
3. 調(diào)整reduce個(gè)數(shù)方法二;
set mapred.reduce.tasks = 15;
select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt;這次有15個(gè)reduce
4. reduce個(gè)數(shù)并不是越多越好;
同map一樣,啟動(dòng)和初始化reduce也會(huì)消耗時(shí)間和資源;
另外,有多少個(gè)reduce,就會(huì)有多少個(gè)輸出文件,如果生成了很多個(gè)小文件,那么如果這些小文件作為下一個(gè)任務(wù)的輸入,則也會(huì)出現(xiàn)小文件過(guò)多的問(wèn)題;
5. 什么情況下只有一個(gè)reduce;
很多時(shí)候你會(huì)發(fā)現(xiàn)任務(wù)中不管數(shù)據(jù)量多大,不管你有沒(méi)有設(shè)置調(diào)整reduce個(gè)數(shù)的參數(shù),任務(wù)中一直都只有一個(gè)reduce任務(wù);
其實(shí)只有一個(gè)reduce任務(wù)的情況,除了數(shù)據(jù)量小于hive.exec.reducers.bytes.per.reducer參數(shù)值的情況外,還有以下原因:
a) 沒(méi)有g(shù)roup by的匯總,比如把select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt; 寫(xiě)成 select count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04';
這點(diǎn)非常常見(jiàn),希望大家盡量改寫(xiě)。
b) 用了Order by
c) 有笛卡爾積
通常這些情況下,除了找辦法來(lái)變通和避免,我暫時(shí)沒(méi)有什么好的辦法,因?yàn)檫@些操作都是全局的,所以hadoop不得不用一個(gè)reduce去完成;
同樣的,在設(shè)置reduce個(gè)數(shù)的時(shí)候也需要考慮這兩個(gè)原則:使大數(shù)據(jù)量利用合適的reduce數(shù);使單個(gè)reduce任務(wù)處理合適的數(shù)據(jù)量。
以上是“如何控制hive任務(wù)中的map數(shù)和reduce數(shù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!