20
2021
01

你是如何发现Hive数据倾斜?

通过 yarn 监控平台的 task 信息查看到有个别的 task 执行时间过于缓慢,甚至还会挂掉。


解决办法

1 合理设置Map数

1) 通常情况下,作业会通过input的目录产生一个或者多个map任务。


主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。


举例:

a)  假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数。

b) 假设input目录下有3个文件a,b,c大小分别为10m,20m,150m,那么hadoop会分隔成4个块(10m,20m,128m,22m),从而产生4个map数。即,如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。


2) 是不是map数越多越好?


  答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。


3) 是不是保证每个map处理接近128m的文件块,就高枕无忧了?


答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。


针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;


2 小文件合并

在map执行前合并小文件,减少map数:


CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)


set mapred.max.split.size=112345600;

set mapred.min.split.size.per.node=112345600;

set mapred.min.split.size.per.rack=112345600;

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;


这个参数表示执行前进行小文件合并,前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),进行合并。


3 复杂文件增加Map数

当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。


增加map的方法为


根据 computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))公式

调整maxSize最大值。让maxSize最大值低于blocksize就可以增加map的个数。

mapreduce.input.fileinputformat.split.minsize=1 默认值为1


mapreduce.input.fileinputformat.split.maxsize=Long.MAXValue 默认值Long.MAXValue因此,默认情况下,切片大小=blocksize 


maxsize(切片最大值): 参数如果调到比blocksize小,则会让切片变小,而且就等于配置的这个参数的值。


minsize(切片最小值): 参数调的比blockSize大,则可以让切片变得比blocksize还大。


例如

--设置maxsize大小为10M,也就是说一个fileSplit的大小为10M

set mapreduce.input.fileinputformat.split.maxsize=10485760;


4 合理设置Reduce数

1、调整reduce个数方法一


1)每个Reduce处理的数据量默认是256MB


set hive.exec.reducers.bytes.per.reducer=256000000;


2)每个任务最大的reduce数,默认为1009


set hive.exec.reducers.max=1009;


3)计算reducer数的公式


N=min(参数2,总输入数据量/参数1)


2、调整reduce个数方法二


--设置每一个job中reduce个数

set mapreduce.job.reduces=3;


3、reduce个数并不是越多越好


过多的启动和初始化reduce也会消耗时间和资源;


同时过多的reduce会生成很多个文件,也有可能出现小文件问题


总的来说就是,数据倾斜的根源是key分布不均匀,所以应对方案要么是从源头解决(不让数据分区,直接在map端搞定),要么就是在分区时将这些集中却无效的key过滤(清洗)掉,或者是想办法将这些key打乱(给key加上标签),让它们进入到不同的reduce中。

« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。