![](https://csdnimg.cn/release/download_crawler_static/89110763/bg6.jpg)
数据倾斜是分布式系统不可避免的问题,任何分布式系统都有几率发生数据倾斜,但有些小伙伴在平时工
作中感知不是很明显,这里要注意本篇文章的标题
千亿级数据
,为什么说千亿级,因为如果一个任务的
数据量只有几百万,它即使发生了数据倾斜,所有数据都跑到一台机器去执行,对于几百万的数据量,一
台机器执行起来还是毫无压力的,这时数据倾斜对我们感知不大,只有数据达到一个量级时,一台机器应
付不了这么多的数据,这时如果发生数据倾斜,那么最后就很难算出结果。
所以就需要我们对数据倾斜的问题进行优化,尽量避免或减轻数据倾斜带来的影响。
在解决数据倾斜问题之前,还要再提一句:没有瓶颈时谈论优化,都是自寻烦恼。
大家想想,在
map
和
reduce
两个阶段中,最容易出现数据倾斜的就是
reduce
阶段,因为
map
到
reduce
会经
过
shuffle
阶段,在
shuffle
中默认会按照
key
进行
hash
,如果相同的
key
过多,那么
hash
的结果就是大量相同
的
key
进入到同一个
reduce
中,导致数据倾斜。
那么有没有可能在
map
阶段就发生数据倾斜呢,是有这种可能的。
一个任务中,数据文件在进入
map
阶段之前会进行切分,默认是
128M
一个数据块,但是如果当对文件使
用
GZIP
压缩等不支持文件分割操作的压缩方式时,
MR
任务读取压缩后的文件时,是对它切分不了的,该压
缩文件只会被一个任务所读取,如果有一个超大的不可切分的压缩文件被一个
map
读取时,就会发生
map
阶
段的数据倾斜。
所以,从本质上来说,发生数据倾斜的原因有两种:一是任务中需要处理大量相同的
key
的数据。二是任务
读取不可分割的大文件。
数据倾斜解决方案
MapReduce
和
Spark
中的数据倾斜解决方案原理都是类似的,以下讨论
Hive
使用
MapReduce
引擎引发的数据
倾斜,
Spark
数据倾斜也可以此为参照。
1. 空值引发的数据倾斜
实际业务中有些大量的
null
值或者一些无意义的数据参与到计算作业中,表中有大量的
null
值,如果表之间
进行
join
操作,就会有
shuffle
产生,这样所有的
null
值都会被分配到一个
reduce
中,必然产生数据倾斜。
之前有小伙伴问,如果
A
、
B
两表
join
操作,假如
A
表中需要
join
的字段为
null
,但是
B
表中需要
join
的字段不
为
null
,这两个字段根本就
join
不上啊,为什么还会放到一个
reduce
中呢?
这里我们需要明确一个概念,数据放到同一个
reduce
中的原因不是因为字段能不能
join
上,而是因
为
shuffle
阶段的
hash
操作,只要
key
的
hash
结果是一样的,它们就会被拉到同一个
reduce
中。
解决方案:
第一种:可以直接不让
null
值参与
join
操作,即不让
null
值有
shuffle
阶段