hive中控制map和reduce数量的简单实现方法

转载:https://blog.csdn.net/zhong_han_jun/article/details/50814246

 

0、先说结论:
  由于mapreduce中没有办法直接控制map数量,所以只能曲线救国,通过设置每个map中处理的数据量进行设置;reduce是可以直接设置的。
控制map和reduce的参数

set mapred.max.split.size=256000000; -- 决定每个map处理的最大的文件大小,单位为B
set mapred.min.split.size.per.node=1; -- 节点中可以处理的最小的文件大小
set mapred.min.split.size.per.rack=1; -- 机架中可以处理的最小的文件大小
方法1
set mapred.reduce.tasks=10; -- 设置reduce的数量
方法2
set hive.exec.reducers.bytes.per.reducer=1073741824 -- 每个reduce处理的数据量,默认1GB

补充说明:一个集群可以有多个机架,一个机架有1至多个节点,这里的集群是mapreduce不是yarn,yarn没有详细了解过,另外如果想要实现map中的数据合并需要设置下面的参数,集群默认就是这个格式

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
1
需要确认的问题:
 a.我们该设置多少个map多少个reduce才合适?
  map数普遍是通过执行时长来确认的,至少应当保证每个map执行时长在1分钟以上,太短的话意味着大量重复的jvm启用和销毁。具体设置要根据具体任务来处理,有些任务占用cpu大,有些占用io大。
  我这边的话因为大任务经常搞了上千个map,作为小集群影响还是蛮大的,所以只对监控到的hql产生过大的map和reduce进行调整,经过一些简单测试,map数保证在三四百个其实不影响执行效率。

 b.设置了上面的参数会带来什么影响?
  设置map的话,影响不是很大,可能会带来更多的集群之间的io,毕竟要做节点之间的文件合并
  设置reduce的话,如果使用mapred.reduce.tasks,这个影响就大了,至少会造成同一个session每一个mr的job的reduce都是这么多个,而且reduce个数意味着最后的文件数量的输出,如果小文件太多的话可以打开reduce端的小文件合并参数,set hive.merge.mapredfiles=true

1、控制map数量的三个参数的逻辑概念
  可以简单的理解为集群对一个表分区下面的文件进行分发到各个节点,之后根据mapred.max.split.size确认要启动多少个map数,逻辑如下
  a.假设有两个文件大小分别为(256M,280M)被分配到节点A,那么会启动两个map,剩余的文件大小为10MB和35MB因为每个大小都不足241MB会先做保留
  b.根据参数set mapred.min.split.size.per.node看剩余的大小情况并进行合并,如果值为1,表示a中每个剩余文件都会自己起一个map,这里会起两个,如果设置为大于45*1024*1024则会合并成一个块,并产生一个map
  如果mapred.min.split.size.per.node为10*1024*1024,那么在这个节点上一共会有4个map,处理的大小为(245MB,245MB,10MB,10MB,10MB,10MB),余下9MB
  如果mapred.min.split.size.per.node为45*1024*1024,那么会有三个map,处理的大小为(245MB,245MB,45MB)
  实际中mapred.min.split.size.per.node无法准确地设置成45*1024*1024,会有剩余并保留带下一步进行判断处理
  c. 对b中余出来的文件与其它节点余出来的文件根据mapred.min.split.size.per.rack大小进行判断是否合并,对再次余出来的文件独自产生一个map处理

2、控制map数量的简单实用方式
  我们执行一个hive语句,发现起了1000个map,这种情况对于当前的数据量来说是完全不必要的,同时还会影响其它用户提交任务
  这个时候希望map减小到250个左右,很简单
  将map处理的最大的文件大小增大,256000000*4=1024000000
参数修改为如下

set mapred.max.split.size=1024000000;
set mapred.min.split.size.per.node=1024000000;
set mapred.min.split.size.per.rack=1024000000;

示例及测试如下

  修改参数之后,如下图,可以看到map数量减少到370,至于为什么单个map处理的数据量增大了,map数却不是按倍数减少到1185/4=296个,原因在文件合并过程中对于如何起map数并不是单纯的看总的文件大小,存在一些更优化的算法,如考虑带宽、IO、当前map分配等


3、控制reduce参数
  修改reduce的个数就简单很多,直接根据可能的情况作个简单的判断确认需要的reduce数量,如果无法判断,根据当前map数减小10倍,保持在1~100个reduce即可(注意,这个不同的集群需求不同哈)
设置参数如下
set mapred.reduce.tasks=10
不建议随意设置reduce参数哈,可能调整参数更好一点
set hive.exec.reducers.bytes.per.reducer=1073741824

4、控制map和rduce数的说明
  1、因为set参数的设置是session级别的,Toad for Cloud(青蛙)第三方软件中暂时没有发现如何使set的参数设置有效的,所以请使用CRT等工具连接到linux的界面中进行使用,使用hive命令连接hive集群,一次设置只要不结束这次连接,那么参数是始终有效的。
  2、注意各参数的设置大小,不要冲突,否则会异常,大小顺序如下
mapred.max.split.size <= mapred.min.split.size.per.node <= mapred.min.split.size.per.rack
  3、这种减少map数的行为是否能带来更短的执行时间,需要具体分析,map数也不是越少越好,减少了map数,单个map处理的数据量就上升,需要更多的时间,同时也因为需要合并节点内、节点间甚至机架之间的数据需要更多的IO和带宽。
  参数的设置本质是根据文件情况、系统情况、数据计算情况进行的一个平衡考虑,有取有舍,我们需要遵循的规则就是:使大数据量利用合适的map数;使单个map任务处理合适的数据量
  4、reduce数同3

posted on 2021-03-10 17:30  该用户很懒  阅读(580)  评论(0编辑  收藏  举报