1、MapReduce跑的慢的原因
(1)计算机性能
(2)数据倾斜
(3)map和reduce数设置不合理
(4)小文件过多
(5)大量的不可切割的超大文件
(6)spill次数过多
(7)merge次数过多
2、MapReduce优化
(1)数据输入优化
1)合并小文件
大量小文件会产生大量Map任务,增大了map任务的装载次数,任务的装载比较耗时
2)采用CombineTextInputFormat来作为输入,解决输入端的大量小文件场景
(2)map阶段优化
1)减少溢写(spill)次数
通过调整io.sort.mb及sort.spill.percent参数值,增大触发spill的内存上限,减少spill次数,从而减少磁盘IO
2)减少合并(merge)次数
通过调整io.sort.factor参数,增大merge的文件数目,减少merge的次数,从而缩短MR作业的处理时间
3)合理使用Combine
不影响业务逻辑前提下,进行Combine处理,减少IO
(3)Reduce阶段优化
1)合理设置Map和Reduce数
设置太少会导致Task等待,延长处理时间,
设置太多会导致map,reduce任务间竞争资源,造成处理超时错误
2)设置map、reduce共存
调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间
3)规避使用reduce
因为reduce在用于连接数据集的时候将会产生大量的网络消耗
4)合理设置reduce端的Buffer
默认情况下,数据到达一个阈值的时候,Buffer中的数据就会写入磁盘,然后Reduce会从磁盘中获得所有数据。中间 多次写磁盘->读磁盘。此时可以调整此参数来配置,使得Buffer的一部分数据可以直接给Reduce,减少IO开销
mapreduce.reduce.input.buffer.percent默认为0.0。当值大于0,会保留指定比例的内存读Buffer中的数据直接给 Reduce使用。
(4)IO传输优化
1)采用数据压缩方式
减少网络IO的时间,安装Snappy和Lzo压缩编码器
2)使用SequenceFile二进制文件
(5)数据倾斜优化
1)抽样和范围分区
对原始数据进行抽样得到的结果集来预设分区边界值
2)自定义分区
基于输出键的背景知识进行自定义分区
3)Combine
使用Combine可以大量减少数据倾斜
4)采用MapJoin,尽量避免使用ReduceJoin
(6)常用调优参数
配置参数 | 参数说明 |
mapreduce.map.memory.mb | 一个MapTask可使用的资源上限(单位:MB),默认为1024。如果MapTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.reduce.memory.mb | 一个ReduceTask可使用的资源上限(单位:MB),默认为1024。如果ReduceTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.map.cpu.vcores | 每个MapTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.cpu.vcores | 每个ReduceTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.shuffle.parallelcopies | 每个Reduce去Map中取数据的并行数。默认值是5 |
mapreduce.reduce.shuffle.merge.percent | Buffer中的数据达到多少比例开始写入磁盘。默认值0.66 |
mapreduce.reduce.shuffle.input.buffer.percent | Buffer大小占Reduce可用内存的比例。默认值0.7 |
mapreduce.reduce.input.buffer.percent | 指定多少比例的内存用来存放Buffer中的数据,默认值是0.0 |