1.设置map个数
map个数无法直接设置,只能通过设置切片大小来间接增大或减小map个数
首先需要明白两个参数的含义
mapred.min.split.size:这个参数指定了切片的最小大小,它决定了文件是否需要切片。如果文件大小小于这个值,则不会进行切片。默认值为1字节,但设置过小会导致处理速度变慢。
mapred.max.split.size:这个参数指定了切片的最大大小。当文件大于这个值时,会被分成多个切片。默认值为256mb。
具体分如下两种情况:
1、小文件(1-10m)过多
mapred.min.split.size设置为1m或其他大小,而mapred.max.split.size默认值
此时当大于1m,但小于256m的文件都会被合并,最终合并的大小不超过256m,但需要注意的是,这部分文件会被先切分成1m,再向256m进行合并,这中间的切分其实是有一定开销在里边的,所以我们要保证,文件最好都是这个大小范围,而不是有很多过大的文件或者过小的文件,因为小于1m过多会牺牲掉小文件合并,而单独启动多个map
同时我们在估算map数量时其实还要考虑到一个副本问题:
如果输入文件为多个文件,它有三个副本,每个文件可能来自不同的副本,而不同的副本都存在于不同的节点和机架,即每个节点内的文件可以按照上述规则切分,但由于per.node默认为1,会暂存于block,最后暂存于三个节点的碎片会每个合成一个split,
和我们设想的map个数并不一样,比如,我们现在该目录下游60个大小为3k左右的文件,加一起也就是180k,但最后的map数却是三个,此时如何让多个节点上的文件合并在一起是个问题


在开启了org.apache.hadoop.hive.ql.io.combinehiveinputformat后,一个data node节点上多个小文件会进行合并,合并文件数由mapred.max.split.size限制的大小决定。
mapred.min.split.size.per.node决定了多个data node上的文件是否需要合并mapred.min.split.size.per.rack决定了多个交换机上的文件是否需要合并
set mapred.max.split.size=256000000
set mapred.min.split.size.per.node=256000000
set mapred.min.split.size.per.rack=256000000
所以通常我们将这三个参数都设置为同一个值,来达到我们想要的一个map处理的文件大小为256m的需求,即一个节点内文件会朝256m目标合并,如果不到256m,则暂存,不同节点和机架拿着暂存的碎片,继续朝着这个目标合并,使最后的文件大小向256m靠近
2、大文件(100m左右)过多
mapred.min.split.size设置为128m或其他大小,maxsize默认
此时小于128m的文件将不会进行合并,虽然牺牲了小文件合并,但是换来的是防止所有超过1字节(minsize默认1字节)的文件都会被先切分成1字节,再向256m进行合并中间的消耗
3、总结
maxsize是切片的最大限制,作用有2:
1、超过该值的大文件根据该值切片;2、不超过该值的文件,朝该值所设大小合并
minsize是是否要切片的最小限制,作用也有2:
1、超过该值的文件再结合maxsize决定要不要进行合并,合并的时候先将文件切分成该值(极小的切片);2、不超过该值的文件直接不切片也不合并,直接启动一个map
minsize尤其重要,它设置的多与少,取决于大多数文件的大小,你需要找到一个均衡点,既让大多数偏小(这里的偏小偏大没有绝对意义上的大与小,只是相对其他文件的比较)的文件可以参与合并,又让大多数偏大的文件不用先切分的极小,再进行合并
2.设置reduce个数
reduce个数的计算逻辑没有map那样复杂,通常可以直接指定个数
set hive.exec.reducers.max=1,
set mapred.reduce.tasks=1
其中mapred.reduce.tasks和hive.exec.reducers.max设置一个即可,前者代表所有任务中的reduce个数,后者代表每个任务也就是stage的最大个数,当底层公式计算的个数比该值大时,生效该值,小时生效计算值
但这里无论生效哪个,当reducetask个数设置时,直接以reducetask为准,公式为nvl(reducetask, min(reducemax, min(1009, 程序计算)))
假如我们未设置reducetask,但设置了reducemax为10,此时程序计算出需要2000个reduce,但reduce上限默认是1009个,但reducemax为10,故最终为10个reduce
假如我们未设置reducetask,但设置了reducemax为10,此时程序计算出需要2个reduce,则经过两次取最小值,故最终为2个reduce
但如果我们设置reducetask为5,不管里面是需要10个还是2个reduce,最终都为5个reduce
故如果我们想让reduce个数固定为某个值,则设置mapred.reduce.tasks,如果我们想让个数尽可能小于某个值,则设置hive.exec.reducers.max
3.设置map和reduce输出文件合并大小
map only任务有时候能合并有时候不能合并,原因是hive.merge.smallfiles.avgsize默认值为16m
这是个判断参数,也就是说当输出文件的平均大小小于该值时才会合并,分区表是分区下的文件平均值小于该值合并,
和hive.merge.mapfiles无关,map端输出合并和reduce端输出合并参数默认就是打开的
比如我们输出的两个文件,一个为11m,一个17m,平均小于16m,则合并,会另外再走一个合并的stage
如果我们输出的两个文件,一个为1m,一个为100m,平均大小大于16m,则不合并,不会走合并的stage
4.其他一些常用设置
设置map和reduce核数(并行度):
set mapreduce.map.cpu.vcores=2
set mapreduce.reduce.cpu.vcores=10
设置map进行到多少时开始reduce:
set mapreduce.job.reduce.slowstart.completedmaps=0.4
发表评论