hive数据倾斜主要是由shuffle引起的,而引起shuffle的又主要有四种情况,分别为:
1.group by
2.join
3.count(distinct)
4.开窗函数
1.group by
关于group by的数据倾斜,hive自带了两个配置调整:
1.Map端预聚合。通过hive.map.aggr = true,遇到group by时,会先开启一个combiner进行预聚合,减少shuffle后进入reduce的数据量
2.倾斜均衡配置项。通过hive.groupby.skewindata = true。在group by 时会启动两个MR job,第一个job会将map端数据随机输入 reducer,每个reducer做部分预聚合,相同的key会分配到不同reducer中。第二个job再将前面预处理过的数据按照key聚合并输出结果。
2.join
1.使用map join。Set hive.auto.convert.join = true,set hive.mapjoin.smalltable.filesize = 2500000开启。表小于此值则会被加载进入内存,在map端完成join操作,避免了shuffle。
2.倾斜均衡配置。Hive.optimize.skewjoin = true。如果开启,在join过程中hive会将计算超过阈值hive.skewjoin.key = 默认100000的倾斜key对应行临时写进文件,然后再启动另外一个job做map join生成结果。通过hive.skewjoin.mapjoin.map.tasks参与可以控制第二个job 的mapper数量默认10000。
3.无意义的值或空值。可以采用where过滤,如果需要保留,则将控制key用随机打散方式打散,主要要标注为无意义的打散值与正常值区分,如负数,小数等。
4.单独处理倾斜key。针对某些单独倾斜key,我们可以采用预处理或者预聚合方式进行操作。避免所有数据都进入到一个分区。注意:可以采用加盐值前缀方法,进行预聚合再去掉随即前缀进行最终聚合。只是这种方式会增长数据处理的步长。所以我们一般不考虑。。
5.build table过大。有时,build table会大到无法直接使用map join的地步,比如全量用户维度表,而使用普通join又有数据分布不均的问题。这时就要充分利用probe table的限制条件,削减build table的数据量,再使用map join解决。代价就是需要进行两次join。
3和4
关于3和4其实是由于函数引起的。主要还是考虑能否使用更优质的函数进行替代,或者转换成group by 或者 join操作,然后再进行以上的优化。