您的位置:首页 > 其它

hive map reduce 参数设置

2018-03-12 16:51 134 查看
现象:
1.目前每日load出来的问题sql,最终的结果文件里面很多都只有一条数据。
2.资源影响巨大,对照脚本统计出来的sql运行时间,手动执行sql的时间是其十分之一到三分之一。
3.不少sql执行时的map数量能达到1000-3000,但是reduce数量在1左右。
由于每天load出的excle文档,sjzx租户的sql过长,手动无法执行,其它租户的sql抽取时又存在乱码问题,仅针对了sjzx_b租户的sql进行了分析,但是问题和优化可通用。
 
首先mapreduce中map数量是无法直接控制的,所以只能通过对map数量的影响因素方面进行调整,从而间接影响hive sql执行时map的数量。
 
目前我们集群的情况:
(set) mapred.max.split.size=256000000   -------决定每个map处理的最大文件大小,B
(set) mapred.min.split.size.per.node=1    -------节点处理的最小文件大小
(set) mapred.min.split.size.per.rack=1     ------机架中可以处理的最小文件大小
(set) mapred.reduce.tasks=-1            ------设置reduce数量,这里-1也就是自动计算出需要reduce的个数
(set) hive.exec.reducers.bytes.per.reducer=256000000
   ---------每个reduce处理的数据量
 
(set) hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
                               ---------map端做combiner操作
 
(set) hive.merge.mapredfiles=true        ---------小文件合并
 
(set) hive.exec.reducers.bytes.per.reducer=256000000------控制一个job当中会有多少个reduce来处理,依据的是输入文件的总大小
 
(set) hive.exec.reducers.max=1009    ----------控制最大reduce数量
 
 
调整影响:
设置map,可能带来集群之间的io,因为可能涉及到文件的合并;设置reduce,则会对最后的结果文件个数造成直接影响;reduce太少,会导致reduce端的数据量太大,影响执行效率,导致整个job都不能结束;reduce太小,则会产生大量的结果文件,合并代价大,占用namenode的内存空间。
 
逻辑:
根据mapred.max.split.size来确认需要启动多少个map数。
比如文件大小260M,280M,则会启动两个map,剩余的4M,24M先做保留。
再根据mapred.min.split.size.per.node来针对剩下的文件做操作,如果设置为1,则表示剩余的文件自己启动一个map,这里会启动2两个;如果设置为28*1024*1024,则文件会合并成一个,启动一个map。但是正常情况下,不可能正好设置成28*1024*1024,也就是说,还是会产生剩余的文件。
最后根据mapred.min.split.size.per.rack,来决定是否要进行合并,对再次剩余的文件独自产生一个map。
 
因此针对控制map数量和reduce数量:
针对map数量:
set mapred.max.split.size=
set mapred.min.split.size.per.node=
set mapred.min.split.size.per.rack=
针对reduce数量:
set mapred.reduce.tasks=
set hive.exec.reducers.bytes.per.reducer=
 
 
优化手段:
1.针对那些map数量达到1000-3000的sql,可以通过设置mapred.max.split.size临时参数来减少map数量,目前测试的结果显示1000-2000map数量的sql,设置在512M,2000-3000map数量的设置在1G,运行时间有明显减少
 
 
2.count(distinct xxx)语句的改写
比如:
insert into table lzl2 partition(date_dt = '2018-02-03') select 'FIN_PG_BAL_ITEM_71' ,count(distinct bal_item_id) from FIN_PG_BAL_ITEM_71
这个sql执行时间是57分钟,map数量367,reduce数量1。
时间如此之长的分析:
Mapreduce过程中,理论上map阶段会进行combine操作对输出结果做合并消重,以减少reduce阶段的数据量。但是如果使用了distinct,就会发生map阶段无法进行combine操作,对统计大量数据时,会导致最终map的全部输出由单个reduce task来处理,也就是说这个唯一的reduce task需要shuffle大量的数据,并且要进行排序聚合等处理,会导致map过程可能十几秒就完成,但是reduce过程需要长达30-50分钟。
直接增加reduce数量,set mapred.reduce.tasks=10;但是在执行过程中,发现reduce数量不管怎么改,实际运行时都是1。
这是因为hive在处理count这种全聚合操作时,会忽略掉用户指定的reduce task数量,而强制使用1,这样会造成单一的reduce task瓶颈。
改写成:
insert into table lzl2 partition(date_dt = '2018-02-03') select 'FIN_PG_BAL_ITEM_71' ,t.b from (select count(*) as b from (select distinct bal_item_id from pdm.FIN_PG_BAL_ITEM_71) a) t;
第一阶段:map数量358,reduce数量485
第二阶段:map数量179,reduce数量1
总执行时长117秒。
分析:
这样改写的sql在执行时,会被分成两个job。
第一阶段job是选出全部的非重复bal_item_id,虽然在这阶段由于distinct对map阶段的combine产生了抑制,但是可以通过调整reduce的数量来提高这阶段shuffle效率,这里我进行了两种对比,set mapred.reduce.tasks=-1和set mapred.reduce.tasks=
10,前者表示让mr自己去计算需要启动多少个reduce,后者认为设置,由于无法相对准备的给出reduce的数量,所以后者的效率还是不算高,因此选择了默认配置set mapred.reduce.tasks=-1。
PS:默认设置很省事,但是绝不是最佳,前期优化可以这样选择。
 
第二阶段job,进行count(*),虽然这阶段强制指定了reduce task,但是由于第一阶段的job已经对数据进行合并去重的操作,这阶段的map只需输出一个合并后的计数即可,因此较少的map输出不会成为单一reduce task的瓶颈。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hive mapreduce