mapreduce中map和reduce個數

2022-09-07 15:09:18 字數 4222 閱讀 9341

一、    控制hive任務中的map數: 

1.    通常情況下,作業會通過input的目錄產生乙個或者多個map任務。 

主要的決定因素有: input的檔案總個數,input的檔案大小,集群設定的檔案塊大小(目前為128m, 可在hive中通過set dfs.block.size;命令檢視到,該引數不能自定義修改);

2.    舉例: 

a)    假設input目錄下有1個檔案a,大小為780m,那麼hadoop會將該檔案a分隔成7個塊(6個128m的塊和1個12m的塊),從而產生7個map數

b)    假設input目錄下有3個檔案a,b,c,大小分別為10m,20m,130m,那麼hadoop會分隔成4個塊(10m,20m,128m,2m),從而產生4個map數

即,如果檔案大於塊大小(128m),那麼會拆分,如果小於塊大小,則把該檔案當成乙個塊。

3.    是不是map數越多越好? 

答案是否定的。如果乙個任務有很多小檔案(遠遠小於塊大小128m),則每個小檔案也會被當做乙個塊,用乙個map任務來完成,

而乙個map任務啟動和初始化的時間遠遠大於邏輯處理的時間,就會造成很大的資源浪費。

而且,同時可執行的map數是受限的。

4.    是不是保證每個map處理接近128m的檔案塊,就高枕無憂了? 

答案也是不一定。比如有乙個127m的檔案,正常會用乙個map去完成,但這個檔案只有乙個或者兩個小字段,卻有幾千萬的記錄,

如果map處理的邏輯比較複雜,用乙個map任務去做,肯定也比較耗時。

針對上面的問題3和4,我們需要採取兩種方式來解決:即減少map數和增加map數;

如何合併小檔案,減少map數? 

假設乙個sql任務:

select count(1) from popt_tbaccountcopy_mes where pt = 『2012-07-04』;

該任務的inputdir  /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04

共有194個檔案,其中很多是遠遠小於128m的小檔案,總大小9g,正常執行會用194個map任務。

map總共消耗的計算資源: slots_millis_maps= 623,020

我通過以下方法來在map執行前合併小檔案,減少map數:

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;

再執行上面的語句,用了74個map任務,map消耗的計算資源:slots_millis_maps= 333,500

對於這個簡單sql任務,執行時間上可能差不多,但節省了一半的計算資源。

大概解釋一下,100000000表示100m, set hive.input.format=org.apache.hadoop.hive.ql.io.combinehiveinputformat;這個引數表示執行前進行小檔案合併,

前面三個引數確定合併檔案塊的大小,大於檔案塊大小128m的,按照128m來分隔,小於128m,大於100m的,按照100m來分隔,把那些小於100m的(包括小檔案和分隔大檔案剩下的),

進行合併,最終生成了74個塊。

如何適當的增加map數? 

當input的檔案都很大,任務邏輯複雜,map執行非常慢的時候,可以考慮增加map數,來使得每個map處理的資料量減少,從而提高任務的執行效率。

假設有這樣乙個任務:

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去完成這個任務,肯定是比較耗時的,這種情況下,我們要考慮將這乙個檔案合理的拆分成多個,

這樣就可以用多個map任務去完成。

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任務去完成。

每個map任務處理大於12m(幾百萬記錄)的資料,效率肯定會好很多。

看上去,貌似這兩種有些矛盾,乙個是要合併小檔案,乙個是要把大檔案拆成小檔案,這點正是重點需要關注的地方,

根據實際情況,控制map數量需要遵循兩個原則:使大資料量利用合適的map數;使單個map任務處理合適的資料量;

二、    控制hive任務的reduce數: 

1.    hive自己如何確定reduce數: 

reduce個數的設定極大影響任務執行效率,不指定reduce個數的情況下,hive會猜測確定乙個reduce個數,基於以下兩個設定:

hive.exec.reducers.bytes.per.reducer(每個reduce任務處理的資料量,預設為1000^3=1g) 

hive.exec.reducers.max(每個任務最大的reduce數,預設為999)

計算reducer數的公式很簡單n=min(引數2,總輸入資料量/引數1)

即,如果reduce的輸入(map的輸出)總大小不超過1g,那麼只會有乙個reduce任務;

如: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.    調整reduce個數方法一: 

調整hive.exec.reducers.bytes.per.reducer引數的值;

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.    調整reduce個數方法二; 

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個數並不是越多越好; 

同map一樣,啟動和初始化reduce也會消耗時間和資源;

另外,有多少個reduce,就會有多少個輸出檔案,如果生成了很多個小檔案,那麼如果這些小檔案作為下乙個任務的輸入,則也會出現小檔案過多的問題;

5.    什麼情況下只有乙個reduce; 

很多時候你會發現任務中不管資料量多大,不管你有沒有設定調整reduce個數的引數,任務中一直都只有乙個reduce任務;

其實只有乙個reduce任務的情況,除了資料量小於hive.exec.reducers.bytes.per.reducer引數值的情況外,還有以下原因:

a)    沒有group 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去完成;

同樣的,在設定reduce個數的時候也需要考慮這兩個原則:使大資料量利用合適的reduce數;使單個reduce任務處理合適的資料量;

MapReduce中的map個數

在map階段讀取資料前,fileinputformat會將輸入檔案分割成split。split的個數決定了 map的個數。影響map個數 split個數 的主要因素有 1 檔案的大小。當塊 dfs.block.size 為128m時,如果輸入檔案為128m,會被劃分為1個split 當塊為256m,...

mapreduce中map個數的確定

在map階段讀取資料前,fileinputformat會將輸入檔案分割成split。split的個數決定了 map的個數。影響map個數,即split個數的因素主要有 1 hdfs塊的大小,即hdfs中dfs.block.size的值。如果有乙個輸入檔案為1024m,當塊為 256m時,會被劃分為4...

mapreduce中MAP數量如何控制?

一 果斷先上結論 1.如果想增加map個數,則設定mapred.map.tasks 為乙個較大的值。2.如果想減小map個數,則設定mapred.min.split.size 為乙個較大的值。3.如果輸入中有很多小檔案,依然想減少map個數,則需要將小檔案merger為大檔案,然後使用準則2。二 原...