Hive中Map任务和Reduce任务数量计算原理
Posted strongyoung88
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive中Map任务和Reduce任务数量计算原理相关的知识,希望对你有一定的参考价值。
Hive中Map任务和Reduce任务数计算原理
MapReduce原理
-
Map阶段(以
FileInputFormat
为例)
步骤:map, partition, sort, combinerInputFormat
负责计算分片,一个分片对应一个Map任务,InputFormat
而且还负责创建RecordReader
,通过RecordReader
的next()
方法,然后循环调用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,即256Mbmapreduce.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,默认256Mbmapreduce.job.reduces
,reduce数量,默认为1hive.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 = 0%, reduce = 0%