2015年7月15日星期三

Hive调优-控制hive中的mapper和reducer数量

一 控制hive任务中的mapper数

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数是受限的。
Map数越多也造成了巨大的资源浪费。

4. 是不是保证每个map处理接近128m的文件块,即map数越少越好?
答案也是否定的。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录;如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。 
任务逻辑复杂
二 控制hive任务中的reducer数

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任务;

2. 调整reducer的个数
方法一:调整hive.exec.reducers.bytes.per.reducer参数的值;
set hive.exec.reducers.bytes.per.reducer=500000000;   --减少每个reducer处理的数据量
方法二;
set mapred.reduce.tasks = 15;
3. reducer个数并不是越多越好;
启动和初始化reduce也会消耗时间和资源; 另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;

4. 只有一个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 和 笛卡尔积
因为这些操作都是全局的,所以hadoop不得不用一个reduce去完成;

没有评论:

发表评论