Hive on tez中map任务数的计算
Hive on tez任务计算map任务是在AM中计算,而不是在hiveserver中计算,有别于hive on mr任务。
hive on tez中计算map任务个数主要分为两个步骤:一是计算splits个数;二是将splits分组,分组数即为map数量
1. 先通过HiveInputFormat.getSplits 初步计算split的个数,实际上是调用FileInputFormat.getSplits计算split个数
计算split的个数需要确定分片大小splitSize,分片大小涉及的参数:数据块大小blockSize,默认值128M;最小分片大小minSize
其中minSize = min(blockSize/2,tez.grouping.min-size)
tez.grouping.min-size默认值为50M, 因此minSize默认为50M
splitSize = max(minSize, min(goalSize, blockSize), 其中goalSize是所有文件大小总和。
备注:goalSize = totalSize / (numSplits == 0 ? 1 : numSplits); 在笔者的环境中计算的numSplits 为0,所以goalSize是所有文件大小总和。
在默认参数情况下, 即blockSize=128M, minSize=50M
当文件总大小 goalSize<50M,splitSize=minSize=50M
当文件总大小 50M<goalSize<128M, splitSize=goalSize
当文件总大小 goalSize>128M,splitSize=128M
计算split个数的流程
遍历输入目录的每个文件:
如果文件大小fileSize>1.1*splitSize, 就划分一个split,大小为splitSize,一直循环直至最后剩余的大小<1.1*splitSize,作为一个split
如果文件大小fileSize<1.1*splitSize, 就直接作为一个split,大小就是文件大小。
--在默认情况下可以近似于一个block就是一个split,如果文件大小小于blockSize,也是一个block
例如: select count(*) from text;
其中text的文件如下:存在3个文件其中一个大小约为45M, 一个约为182M,一个约为320M
根据以上计算,000000_0文件就分为1个split,000000_1文件分为2个split, 000000_2分为3个split,总共6个splits
查看日志打印,在HiveInputFormat.split阶段确实分成6个splits
2. 计算split个数之后,再调用TezSplitGrouper.getGroupedSplits计算map个数。
getGroupedSplits的作用是将步骤1分好的splits进行分组,每组就是一个map,分成多少组就有多少个map。
其分组过程中重要的参数:tez.grouping.split-count(默认值0),tez.grouping.max-size(默认值1G), tez.grouping.min-size(默认值50M)
下文中将这三个参数简称为split-count,max-size,min-size,由该3个参数计算期望的分组数
如果tez.grouping.split-count>0 表示期望分组的个数为split-count, 计算分组就不受max-size和min-size的影响
如果tez.grouping.split-count<=0 期望分组默认为1(由计算得来,集群获取不到yarn资源默认为1),这时计算分组就受 max-size和min-size的影响
期望分组数desiredNumSplits计算规则如下:
如果split-count>0;desiredNumSplits=split-count;
如果split-count<=0;默认desiredNumSplits=1,每组的读入的数据大小lengthPerGroup为总文件大小totalLength;
如果lengthPerGroup>max-size; 则重新调整desiredNumSplits=totalLength/max-size +1
如果lengthPerGroup<min-size;则重新调整desiredNumSplits=totalLength/min-size +1
得到期待的分组后,计算实际分组数
1)当desiredNumSplits >= split个数,就不用分组,按照原来的split个数,有多少split,map任务是就有多少
上述例子 select count(*) from text; 执行前set tez.grouping.split-count=10,那么输出是按照原split个数
2)desiredNumSplits < split个数, 实际分组计算如下:
计算每个分组的处理的数据大小 lengthPerGroup =totalLength/desiredNumSplits;即总大小除以期待分组数
遍历所有splits,累加文件大小记为groupLength,
如果groupLength+下个split大小>lengthPerGroup ;当前已遍历的split就作为一个分组。直至所有split都遍历完毕,计算出所有分组。
上述例子 set tez.grouping.split-count=3; select count(*) from text; 最终计算分组个数为4
- 点赞
- 收藏
- 关注作者
评论(0)