hive中如何控制mapper的數量
參考文檔:https://www.cnblogs.com/1130136248wlxk/articles/5352154.html
1. 決定map的數據的決定因素有: input的文件總個數,input的文件大小,集群設置的文件塊大小(目前為128M, 可在hive中通過set dfs.block.size;命令查看到,該參數不能自定義修改);
2.是不是map數越多越好,如何減少?
a. 不是越多越好,多了會造成資源的浪費;因為map任務的啟動和初始化的時間,遠遠大於邏輯處理的時間;並且,map的數據是有限制的。
b. 可以通過set設置,讓map在執行前合並小文件,從而達到減少map數:
比如: set mapred.max.split.size=100000000; -- 決定每個map處理的最大的文件大小,單位為B
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;---實現map中的數據合並需要設置下面的參數,集群默認就是這個格式
一般如下設置:
set mapred.max.split.size = 256000000;
set mapred.min.split.size.per.node = 128000000;
set mapred.min.split.size.per.rack = 128000000;
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
3. 是不是每個map處理的接近128M的文件塊,就OK了呢? 如果不OK,如何增加map的數量?
a. 並不一定。當文件接近128M,但是里的內容卻非常多的時候並且map處理的邏輯比較復雜。那么用一個map處理,則時間會比較長
b. 把原來的單個文件拆分成多個的文件, 然后使用新的文件來執行sql。
set mapred.reduce.tasks=10;
create table a_1 as
select * from a
distribute by rand(123);
4. 控制map整體原則:
1:大數據量要利用合適的map數;單個map要處理合適的數據量 。
2:map占用資源要合並小文件;map不足要把大文件拆成小文件。
5.reduce簡單總結:
a. 有多少個reduce,就會有多少個輸出文件,如果生成了很多個小文件,那么如果這些小文件作為下一個任務的輸入,則也會出現小文件過多的問題;
b.什么情況下只有一個reduce:
1. 沒有group by就進行count(1)。
2.使用了order by。
3.存在笛卡兒積。因為這些都是全局操作,生成一個文件,就只有1個reduce。
c. set mapred.reduce.tasks/set hive.exec.reducers.bytes.per.reducer=1073741824 -- 每個reduce處理的數據量,默認1GB
6. map數量一些深入的知識:
a. default_num = total_size/block_size,默認情況下map的個數
b.可以通過set mapred.map.tasks = goal_num 來設置期望的map數量,但是這個數量僅在大於default_num 的時候才會生效。
c. 可以通過set mapred.min.split.size來設置每個task的文件大小,但是這個數量在大於block_size的時候才會生效。
split_size = max(mapred.min.split.size,block_size);
split_num = total_szie/split_size
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任務處理合適的數據量;
轉自:
https://www.cnblogs.com/chengdu-jackwu/p/10170895.html
https://www.cnblogs.com/1130136248wlxk/articles/5352154.html