真正讓你明白Hive參數調優系列2:如何控制reduce個數與參數調優

       相比map個數的控制複雜性,reduce個數的設定要相對簡單多了,reduce的個數一般最後決定了輸出文件的個數,二者相等,如果想多輸出文件的個數(這樣文件變小,但有可能程序變慢),那麼可以人爲增加reduce個數。如果想減少文件個數,也可以手動較少reduce個數(同樣可能程序變慢)。但實際開發中,reduce的個數一般通過程序自動推定,而不人爲干涉,因爲人爲控制的話,如果使用不當很容易造成結果不準確,且降低執行效率。

1.控制reduce個數的方式與參數

1.1.首先可以通過參數直接控制最終reduce的個數,使用參數mapred.reduce.tasks

hive> set mapred.reduce.tasks ;
mapred.reduce.tasks=-1   --我們公司使用的官方默認值-1,表示不人爲設置reduce的個數,實際這種方式用的也少。

1.2.在hive中如果不指定reduce個數的情況下,Hive會猜測確定一個reduce個數,基於以下兩個設定

1.set hive.exec.reducers.bytes.per.reducer=300000000  --我們公司默認值 300Mb
 注意:在hive 0.14.0之前默認hive.exec.reducers.bytes.per.reducer默認值是1Gb,每個reduce最多處理1Gb。
 但是在之後版本默認值都是256Mb.這裏我們公司用的是300Mb。爲什麼300Mb寫的是300*1000*1000?因爲網絡傳輸中用的1000,而不是1024機制。
2.set hive.exec.reducers.max=1009    --我們公司默認值,這個值一般不會修改。
 注意,在hive 0.14.0之前默認是999,之後是1009,所以我們公司的也是官方默認值。

3.reduce計算方式:計算reducer數的公式很簡單
Num=min(hive.exec.reducers.max2,map輸出數據量/hive.exec.reducers.bytes.per.reducer)

2.案例演示控制reduce個數的方法

0.數據準備

    這裏文件大表的大小爲23.4G,存儲爲22個文件,平均每個文件大小都在1.1G左右。小表的文件2個,合計58Mb.

[finance]$ hadoop fs -count hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d
1           22        25154158871 hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d
-----------------------------------------------------------------------------------------------------------------------------------
[finance]$ hadoop fs -du -s -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d
23.4 G  hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d
-----------------------------------------------------------------------------------------------------------------------------------
[finance]$ hadoop fs -du -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d
1.1 G  hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000000_0
1.1 G  hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000001_0
...............................

2.1通過hive.exec.reducers.bytes.per.reducer控制reduce個數

2.1.1 使用系統默認的配置參數,系統自動計算reduce個數,這裏需要85個reduce。85*300>23.4G。程序運行時間爲123S.

set mapred.max.split.size=256000000  ;--公司默認值
set mapred.min.split.size=10000000 ; ----公司默認值
set hive.exec.reducers.bytes.per.reducer = 300000000; ----公司默認值

drop table IF EXISTS fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp;
create table fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp
as 
select
 a.id
,a.entid
,a.ancheyear
,b.liqmen
,b.ligprincipal
,a.regno
,a.tel
,a.postalcode
,a.dom
,a.email
,a.busst
,a.empnum
,a.name
,a.updated
,b.etl_time
from fdm_tmp.t_fgeics_company_liquidation_d_tmp  b
right join fdm_tmp.company_liquidation_fgeics_company_ar_d  a
on b.entid = a.entid;

Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 85
Time taken: 123.945 seconds

2.1.2 增大hive.exec.reducers.bytes.per.reducer = 1000000000; 發現需要的reduce變成了26個,減少了一大半。且滿足26*1Gb>23.4G。但程序運行時間增加將近一半237s.


set mapred.max.split.size=256000000;
set mapred.min.split.size=10000000; 
set hive.exec.reducers.bytes.per.reducer = 1000000000;

Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 26
Time taken: 237.104 seconds

2.1.3.降低hive.exec.reducers.bytes.per.reducer = 128000000; 發現需要的reduce變成了,增加到197個。執行時間爲141s.

set mapred.max.split.size=256000000;
set mapred.min.split.size=10000000; 
set hive.exec.reducers.bytes.per.reducer = 128000000;
Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 197
Time taken: 141.371 seconds

2.2 通過mapred.reduce.tasks直接設置reduce個數(慎用)

如下,手動設置reduce的個數爲100個,則reduce的個數就是100個,每個reduce處理的數據按總數據量 /100.

set mapred.max.split.size=256000000;
set mapred.min.split.size=10000000; 
set mapred.reduce.tasks=100;

Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 100

尖叫總結1:

      同map函數一樣,啓動和初始化reduce也會消耗時間和資源。所以reduce的個數不宜過多,且reduce的個數決定了最終輸出文件的個數,如果reduce個數過多則會產生很多小文件,對於以後的計算也會降低效率。

    當然reduce個數如果過少,也會造成單個reduce處理數據量太大也會影響程序的效率。所以一般reduce的個數最好讓程序自己去推定與計算。

     那麼什麼時候可以進行手動設定reduce數量呢?比如系統自動計算的reduce個數,因爲集羣資源不足,造成程序運行出現OOM(內存溢出不足)時,可以根據推定的reduce個數手動增加數量,保證程序在跑的慢的基礎上可以完整運行。

3.reduce的特殊情況,程序只有一個reduce

           什麼情況下程序只有一個reduce呢?一般map輸出的結果值小於hive.exec.reducers.bytes.per.reducer值時,程序只有一個reduce沒有問題,其次手動設置mapred.reduce.tasks=1,這個時候程序只有一個reduce。那麼正常除了這兩種情況下,正常程序還有什麼情況下只有 一個reduce呢?

3.1.代碼用了order by ,因爲order by是全局排序

drop table IF EXISTS fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp;
create table fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp
as 
select
 a.id
,a.entid
,a.ancheyear
,b.liqmen
,b.ligprincipal
,a.regno
,a.tel
,a.postalcode
,a.dom
,a.email
,a.busst
,a.empnum
,a.name
,a.updated
,b.etl_time
from fdm_tmp.t_fgeics_company_liquidation_d_tmp  b
right join fdm_tmp.company_liquidation_fgeics_company_ar_d  a
on b.entid = a.entid
order by a.id ;

Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 85
Hadoop job information for Stage-2: number of mappers: 81; number of reducers: 1

     order by 全局排序針對所有的數據,所以最終所有的數據都要分發給一個reduce去處理。比如這裏23.4G文件使用order by,系統 啓動了兩個MR程序執行。最終使用一個reduce進行排序,極度慢,慎用。

3.2 表關聯時出現了笛卡爾乘積

drop table IF EXISTS fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp;
create table fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp
as 
select
 a.id
,a.entid
,a.ancheyear
,b.liqmen
,b.ligprincipal
,a.regno
,a.tel
,a.postalcode
,a.dom
,a.email
,a.busst
,a.empnum
,a.name
,a.updated
,b.etl_time
from fdm_tmp.t_fgeics_company_liquidation_d_tmp  b
right join fdm_tmp.company_liquidation_fgeics_company_ar_d  a
on True;
Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 1

    表之間進行join時,如果出現 了笛卡爾乘積,需要全局處理,所以MR不得不使用 一個reduce去處理,所以要儘量避免出現這種 情況。

3.3使用count要注意

--1.單獨使用count(1),count(*)要比count(id)快。
因爲列的引用加入增加了序列化和反序列化的問題。但是這時候count仍然只有1個reduce.
add jar /home/bigdata/software/hive/ext-lib/suning-hive-inputformat.jar;
select count(1)
from fdm_ssa.t_fgeics_company_ar_d  
WHERE statis_date = '20190718' ;
Hadoop job information for Stage-1: number of mappers: 248; number of reducers: 1
OK
158746942
Time taken: 46.182 seconds, Fetched: 1 row(s)

-------------------------------------------------------------------------------

--2.改寫加入group by ,稍微快一些,這時候reduce個數不是1.而是129個。

add jar /home/bigdata/software/hive/ext-lib/suning-hive-inputformat.jar;
select 
statis_date,
count(1)
from fdm_ssa.t_fgeics_company_ar_d  
WHERE statis_date = '20190718' 
group by statis_date
;

Hadoop job information for Stage-1: number of mappers: 248; number of reducers: 129
OK
20190718	158746942
Time taken: 44.167 seconds, Fetched: 1 row(s)
---------------------------------------------------------------------------------

真正讓你明白Hive參數調優系列1:控制map個數與性能調優參數

Hive中各種壓縮算法使用詳解與性能分析

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章