Hive中Map任务和Reduce任务数量计算原理

Posted strongyoung88

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive中Map任务和Reduce任务数量计算原理相关的知识,希望对你有一定的参考价值。

Hive中Map任务和Reduce任务数计算原理

MapReduce原理

  • Map阶段(以FileInputFormat为例)
    步骤:map, partition, sort, combiner

    • InputFormat负责计算分片,一个分片对应一个Map任务,InputFormat而且还负责创建RecordReader,通过RecordReadernext()方法,然后循环调用map()方法
    • map()方法的输入为一行文本,处理的结果先是写到内存缓冲区,达到阈值之后,溢写到磁盘,如果多次溢出,则会有多个溢出文件,这些溢出文件经过了分区,排序,而且还可能作过Combiner,map任务结束之后,多个溢出文件会合并成一个,结果写在本地
  • Reduce阶段
    步骤:copy, sort, reduce

    • reduce阶段先会进行copy,如果copy过来的文件很小,则直接copy到内存中,如果文件较大,则copy到磁盘
    • copy完成之后,会进行一个归并,由于在map端已经作过排序,所以,归并其实是在将多个有序的文件合并成一个有序的文件,这个文件中,一个key会生成一条记录,value为这个key对应的数组
    • 对归并后的文件循环调用reduce()方法,对每个key进行处理。

Map数量

hive的Map数量与分片大数量一致,一个分片生成一个Map任务,分片不是数据本身,是记录了数据的位置和长度,长度用于考虑优先运行,位置用于查找数据,一个分片大小的计算取决于使用的InputFormat(具体使用哪个Inputformat可以在执行计划中查看到),不同的InputFormat计算分片的逻辑可能有所不同。

Hadoop程序中,对于FileInputformat,分片的计算方式为:

  • 分片大小splitSize=Math.max(minSize, Math.min(goalSize, blockSize));
  • long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);,totalSize为输入文件的总大小,numSplits为用户配置的map数量(mapreduce.job.maps)
  • minSize,用户配置的最小分片大小
  • blockSize,文件块大小,默认128M

如果小文件太多,默认情况下会生成太多的map,这样很影响效率,所以,对于CombineFileInputFormat,根据节点和机架的因素,会把多个小文件合并成一个分片,生成更少的map数

配置解释:

  • mapreduce.input.fileinputformat.split.maxsize,分片的最大size,默认256000000,即256Mb
  • mapreduce.input.fileinputformat.split.minsize.per.node,最小分片大小,单位byte,默认大小1,如果想配置成256Mb,则为256 * 1000 * 1000,需要注意配置???
  • mapreduce.input.fileinputformat.split.minsize.per.rack
  • mapreduce.job.maps,每个jobe的map任务数量,默认2

Map任务数量调整策略

影响Map数量的因素:文件大小,文件数量,块大小,配置的Map数量,`InputFormat`类
- 调大Map数量
  - 调小`mapreduce.input.fileinputformat.split.maxsize`(`mapred.max.split.size`已过时),当值小于`blockSize`时才有效

- 调小Map数量
  - 调大`mapreduce.input.fileinputformat.split.minsize.per.node`和`mapreduce.input.fileinputformat.split.minsize.per.rack`,当这二者的值大于blockSize才有效,此时最好配合使用`mapreduce.job.max.split.locations`(表示分片最大的location,默认大小为10,表示一个map处理的split的文件不能超过10个节点),如果超过10,则可能会导致数据错误

Reduce数量

Reduce任务的数量,首先是取用户设置的配置reduce数量,如果在没有指定数量的时候,是由程序自动估算出来的,具体情况如下:

1、Map Join的时候,没有reduce数量
2、如果有配置mapreduce.job.reduces,则使用这个值作为reduce数量
3、如果没有配置mapreduce.job.reduces,则进行reduce估算过程,具体的估算过程如下

  • 获取bytesPerReducer,由hive.exec.reducers.bytes.per.reducer配置,默认256Mb
  • 获取maxReducers,由hive.exec.reducers.max配置,默认1009
  • 计算samplePercentage
  • 计算totalInputFileSize,总的输入文件的大小
  • 计算powersOfTwo,如果使用bucket,并且hive.exec.infer.bucket.sort.num.buckets.power.two=true时才生效,默认这个值为false
    再根据以下判断逻辑计算出最终的估算的reduce数量:
	double bytes = Math.max(totalInputFileSize, bytesPerReducer);
    int reducers = (int) Math.ceil(bytes / bytesPerReducer);
    reducers = Math.max(1, reducers);
    reducers = Math.min(maxReducers, reducers);

因此,从公式中可以得出,影响reduce数量的因素包括:输入总大小,每个reduce处理的数据量
reduce的数量与分区没有关系,但最终生成的文件数量与分区有关系,在没有合并reduce的输出的情况下,reduce生成的文件数量等于分区数量或reduce数量

配置解释:

  • hive.exec.reducers.bytes.per.reducer,每个reduce处理的size,默认256Mb
  • mapreduce.job.reduces,reduce数量,默认为1
  • hive.exec.reducers.max,reduce任务的最大数量,默认1009

reduce数量调整策略

  • 调大reduce数量
    • 调大mapreduce.job.reduces,但是要注意,如果这个值太多,会生成多余的空文件,会浪费reduce资源,比如,分区只有20,但这个reduce数量调成30,则会申请30个reduce, 但实际只有20个有用。
    • 调小hive.exec.reducers.bytes.per.reducer,但注意不要调太小,否则容易生成太多小文件

注意:调大reduce的数量,并不等价于提高了并发度,有可能只是多起了reduce的个数,但依然像之前那样倾斜

  • 调小reduce数量
    • 调小mapreduce.job.reduces,可能会影响并行度
    • 调大hive.exec.reducers.bytes.per.reducer,但会增加每个reduce的压力
    • 调小hive.exec.reducers.max

以上是关于Hive中Map任务和Reduce任务数量计算原理的主要内容,如果未能解决你的问题,请参考以下文章

hive如何调整map数和reduce数

Hive 任务卡在 map = 0%, reduce = 0%

hadoop中map和reduce的数量设置问题

hive调优

hive优化之------控制hive任务中的map数和reduce数

hive优化之——控制hive任务中的map数和reduce数