背景
通常在执行HIVE sql,都会控制map 、reduce 个数在一个合理的范围,避免过多的资源浪费。由于hadoop 的每个任务在初始化是都需要一定时间,因此理想状态每个map 执行时间至少超过一分钟。
一、Hive input.format
查看集群hive 默认input.format
hive> set hive.input.format;
hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
一般常见的inputformat 方法
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; #默认
set hive.input.format=org.apache.hadoop.mapred.TextInputFormat
set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
二、Mapreduce 中Map 个数决定因素
MapReduce框架根据用户指定的InputFormat切割数据集,读取数据,并提供给map任务多条键值对进行处理,决定并行启动的map任务数目。MapReduce框架根据用户指定的OutputFormat,把生成的键值对输出为特定格式的数据。
1、TextInputFormat
在 Map 阶段读取数据前,根据InputFormat 方法将输入数据且分成若干个 split,以便确定 Map Task 的个数即 Mapper 的个数,在 MapReduce 框架中,一个 split 就意味着需要一个 Map Task;
Split个数取决于使用了哪种InputFormat,以及待处理的数据文件是否可分割。默认的FileInputFormat将根据block的个数来分割。
默认主要影响因素有
1、HDFS块的大小,即HDFS中dfs.block.size的值
2、文件大小
3、文件个数
4、splitsiez 大小。 分片是按照splitszie的大小进行分割的,一个split的大小在没有设置的情况下,默认等于hdfs block的大小。
在应用程序中可以通过两个参数来对splitsize进行调节,
splitsize=max(minimumsize,min(maximumsize,blocksize))
2、CombineHiveInputFormat
CombineInputFormat的功能,是将一个目录(可能包括多个小文件,不包括子目录)作为一个map的输入,而不是通常使用一个文件作为输入。
1、使用CombineHiveInputFormat,以下三个参数可以控制map 个数
确认set hive.hadoop.supports.splittable.combineinputformat 是否为true ,当为false 时,下面参数设置是没效果的。
hive.hadoop.supports.splittable.combineinputformat :是否支持可切分的CombieInputFormat ,true是支持
最小split 大小
set mapred.min.split.size 或者 set mapreduce.input.fileinputformat.split.minsize
最大split大小
set mapred.max.split.size 或者 set mapreduce.input.fileinputformat.split.maxsize
一个节点上最小的split大小
set mapred.min.split.size.per.node 或者 set mapreduce.input.fileinputformat.split.minsize.per.node
一个机架上最小的split大小
set mapred.min.split.size.per.rack 或者 set mapreduce.input.fileinputformat.split.minsize.per.rack
2、分片过程
I、 遍历node节点,在同一个node上的 input 文件进行合并,若合并超过max.split.size就生成一个新分片。小于时,若大于minsize.per.node,那也创建一个split 。小于时就暂存input文件, 继续合并下一个node节点中的文件。
遍历过程每个node最多生成一个split,为提高并发度,让split尽量分布到不同的node上。
II、 遍历 rack 机架,那么会把相同机架上的 node 中暂存的input文件block,进行合并,当合并文件的block 超过max.split.size就生成一个新分片。小于时,根据size.per.rack 参数,如果大于size.per.rack 则生成一个split ,小于则暂存block.
III、 对跨机架最终剩余的block 进行合并处理,大于max.split.size就生成一个新分片,循环处理,最后剩的数据创建一个split。
总结
注意:
如果只设置split.maxsize那么基本每个分片大小都需凑满split.maxsize
如果split.maxsize,minsize.per.node,minsize.per.rack 三个都没有设置,那是所有输入整合成一个分片!
切片大小默认等于Block大小,避免MR程序读取数据时,导致一个map任务需要大量访问非本地的Block造成网络开销,反而比正常的非合并方式更慢。
参考文章:
https://developer.aliyun.com/article/26262 https://www.jianshu.com/p/f0fe3b644a47