首页 > 代码库 > Hive参数层面优化之二控制Reduce数

Hive参数层面优化之二控制Reduce数

Reduce数决定中间或落地文件数,文件大小和Block大小无关。

1、Reduce个数的决定因素

reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定:

参数1:hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)

参数2: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

最佳实践:通常情况下,有必要手动指定reducer的个数。考虑到map阶段的输出数据量通常会比输入有大幅减少,因此即使不设定reducer个数,重设hive.exec.reducers.max也是很有必要的。依据hadoop的经验,可以将reducer的个数设定为0.95*集群中TaskTracker的个数

 

2、Reduce数过大或过小引发的问题

Reduce数过大将导致:

1)  生成了很多个小文件(最终输出文件有reduce决定,一个reduce一个文件,输出文件的大小和设置的block的大小是没有关系的),那么如果这些小文件作为下一个Job输入,则也会出现小文件过多需要进行合并的问题;

2)  启动和初始化reduce也会消耗时间和资源;

3)  有多少个reduce就会有多少个输出文件;

 

Reduce数过小将导致:

1)  执行耗时;

2)  可能出现数据倾斜(比如:500个map只有1个reduce);

3、调整Reduce个数

调整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

调整reduce个数方法二:mapred.reduce.tasks

Hive中默认值是1;

案例:

在多个作业共享的某个结果集的数据job时,如果只设定了一个reduce,则该job只有一个输出文件,那么后续的多个job使用该job的输出时,只能使用一个map进行处理,速度会非常慢;可以通过设置共享作业的reduce数使得有多个输出,则后续的job就可以多个map并行处理;现实环境中需要根据实际的数据流来设置reduce的个数;

 

那么如何查询文件的数据量呢?

hadoop fs -du 文件名 

 

根据实际数据量来设定合适的reduce个数;

 

多个作业共享的某个结果集的数据job或者某个job被后边多个job多次引用,可设大该参数(reduce数),以便增大后续访问的Map

如果某个job执行完毕后的数据不会再被后续的job继续使用,就无所谓是否通过手工指定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数的常见场景

很多时候你会发现任务中不管数据量多大,不管你有没有设置调整reduce个数的参数,任务中一直都只有一个reduce任务(数据倾斜的表象之一);

1)  除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外;

2)   没有group by的汇总(group by key会按照不同的key分发到不同的reduce上);

比如把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‘;

3)   用了order by(整个作业排序,性能低);

 

5、Reduce数总结

在设置reduce个数的时候也需要考虑这两个原则:

1)  使大数据量利用合适的reduce

2)  使单个reduce任务处理合适的数据量