首页 > 代码库 > 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任务处理合适的数据量;