MapReduce Map的个数分析

1.概述

通常情况下,Map作业会通过input的目录产生一个或者多个map任务
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M,可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改)

2.举例

  • 假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数
  • 假设input目录下有3个文件a,b,c大小分别为10m,30m,150m,那么hadoop会分隔成4个块(10m,30m,128m,22m),从而产生4个map数。即,如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。

3.问题

1.是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

2.是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

4.解决措施

针对问题1,我们可以减少map数:

#该任务共有194个文件,其中很多是小于128M的小文件,总大小9G,正常执行会用194个map任务
#Map总共消耗的计算资源:SLOTS_MILLIS_MAPS= 623,020
#通过以下方法来在map执行前合并小文件,减少map数:
set mapred.max.split.size=112345600;  #split最大值(100M)
set mapred.min.split.size.per.node=112345600; #一个节点上最小的split大小
set mapred.min.split.size.per.rack=112345600; #一个机架上最小的split大小
#执行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
#前面三个参数确定合并文件切片的大小,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的)
#进行合并,最终生成了74个块

针对问题2,我们可以增加map数:

当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。

#有一个文件,大小为120M,但包含几千万的记录,如果用1个map去完成这个任务,#肯定是比较耗时的,这种情况下,我们要考虑将这一个文件合理的拆分成多个,
#这样就可以用多个map任务去完成
set mapred.reduce.tasks=10;

你可能感兴趣的:(大数据,hadoop,mapreduce)