1. 写在前面的话
此处省略150字…
2. Hive中解决数据倾斜的场景
2.1 大表Join小表时的数据倾斜(map join)
在大表Join小表时,解决数据倾斜最好的方式是使用Map Join,避免Shuffle,从而也避免了数据倾斜. map join主要通过下面的参数来调节:
#默认是true
set hive.auto.convert.join=true --开启map join //1.x版本及以后默认是开启的
#设置小表的大小,生产环境可以适当调大
set hive.mapjoin.smalltable.filesize=25000000 --默认小表小于25mb
在map join中,还有如下2个参数经常使用:
set hive.auto.convert.join.noconditionaltask=true;
set hive.auto.convert.join.noconditionaltask.size=60000000;
说明:
- 第一个参数的作用是,在内连接中,除了第一个表之外的其它表是小表的情况,将普通的join转化为Map join时,是否将多个Map join合并为一个Map Join.设为true表示合并.
- 第二个参数是限定表的大小,多个Map join合并成一个Map join时,其小表的总大小必须小于该值才合并.
- 在小表left join大表时,不能将小表写入内存,否则得到错误的结果.inner join,小表在左边或右边都可以.full out join不能使用map join.
2.2 大表Join大表时的数据倾斜
上面的Map Join解决了小表关联的问题,假如关联的是2个大表就不太适用了.小表不小,所以不太适合加载进内存,那么Map Join肯定是不适合的;两个表都不小,所以必然带来大量的网络IO和磁盘IO,所以Reduce Join也不适合.这个时候就可以使用SMB Join,并带来性能很大的提升.
使用SMB Join的前提: 1.创建表时必须是创建分桶表;2.创建表时必须指定sort by排序;3.分桶的字段与sort by排序的字段且和两表关联的字段必须是一样的.
set hive.enforce.bucketing=true; --默认为false,开启后,则写入数据时会自动分桶
set hive.enforce.sorting=true; --默认为false,开启后,插数据到表中会进行强制排序
#如果希望SMB Join能够转换为SMB Map Join,还需要设置以下参数
set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge =true
原理说明:
在map join的时候,两个表是以相同的方式来划分桶的,则处理左边表的某个桶的时候,Mapper是知道表内对应的记录也在右边表的相同的桶内.因此Mapper只需要获取对应的那个桶,然后进行连接就可以.桶中的数据是根据相同的字段进行排序,这样每个桶的join就变成了merge sort,可以进一步提升map join效率.
2.3 group by引起的数据倾斜
2.3.1 key的基数少(即key的值种类不多),但数据量很大引起的数据倾斜
#默认为fasle,这样就会开始map端聚合combiner.可以减少shuffle的数据量.
set hive.map.aggr=true;
2.3.2 个别key的值数据量大,造成这类key的reduce执行太久引起的数据倾斜
#默认为fasle,应设置为true
set hive.groupby.skewindata=