hive中的join操作及其数据倾斜
join操作是一个大数据领域一个常见的话题。归根结底是由于在数据量超大的情况下,join操作会使内存占用飙升。运算的复杂度也随之上升。在进行join操作时,也会更容易发生数据倾斜。这些都是需要考虑的问题。
过去了解到很多关于join操作的知识点,特此总结一下。
join操作可以分为三类:小表join小表、大表join小表、大表join大表
其中小表join小表是不需要考虑的,不会存在内存溢出,也不会因为数据倾斜导致查询缓慢。
一、大表join小表
大表join小表的解决方法也相对简单,那就是map-side-join。
所谓map-said-join就是将小表直接长期驻留在内存中,在map端完成join操作。
hive通过如下配置开启map-said-join:
SET hive.auto.convert.join=true;
SET hive.mapjoin.smalltable.filesize=25000000;
其中,hive.auto.convert.join
参数表示是否自动转换为mapjoin,hive.mapjoin.smalltable.filesize
参数表示小表的大小阈值。如果小表的大小超过这个阈值,那么Hive将不会自动转换为mapjoin。
编写带有join操作的sql语句时要将小表放在join语句的右边,如下:
SELECT /*+MAPJOIN(small_table)*/
large_table.col1, small_table.col2
FROM
large_table JOIN small_table
ON
large_table.key = small_table.key;
二、大表join大表
大表join大表最常用的方法是bucket-map-join,即将大表拆分成小表,小表再做join操作。
所谓bucket-map-join就是将两个要进行join操作的表的join key上做hash bucket,将两张大表分成多张小表。join key经过hash后的值相同就分到同一个表中,此时只需要将hash相同的bucket进行join操作即可。需要注意的是,两个大表中较大的那个表所得出的hash bucket个数应该是较小的表所得出的hash bucket个数的整数倍。
各个小表依然复制到大表所在的map进行mapjoin
实现bucket-map-join的条件
1.启动bucket-map-join,set hive.optimize.bucketmapjoin = true;
2.一个表的bucket数是另一个表bucket数的整数倍
3.bucket列就是join key所在的列
4.必须是应用在map-join场景中
另一种大表join大表常用的方法是SMB join(Sort Merge Bucket Join)
SMB join相比于bucket-map-join而言多了两个限制条件:
1.要求必须有序
2.要求两个大表所生成的bucket数必须相同
下表给出两者对比:
bucket map join | SMB join |
---|---|
set hive.optimize.bucketmapjoin = true; | set hive.optimize.bucketmapjoin = true;set hive.auto.convert.sortmerge.join=true;set hive.optimize.bucketmapjoin.sortedmerge = true;set hive.auto.convert.sortmerge.join.noconditionaltask=true; |
一个表的bucket数是另一个表bucket数的整数倍 | 两个表的bucket数必须相同 |
bucket列 == join列 | bucket列 == join列 |
必须是应用在map join的场景中 | 必须是应用在bucket map join 的场景中 |
需要注意的是,用户需要自己保证SMB join时数据的有序。如果不是有序的,会导致结果出错。
1.hive.enforce.sorting设置为true。开启强制排序时,插数据到表中会进行强制排序,默认false
2.插入数据时可以在sql中使用distributed c1 sort by c1 或者cluster by c1
另外,表创建时必须时CLUSTERED且SORTED,如下:
create table test_smb_2(mid string,age_id string)
CLUSTERED BY(mid) SORTED BY(mid) INTO 500 BUCKETS;
##三、join操作中的数据倾斜
如果在join操作的过程中发生数据倾斜,那么就需要采用skew join来解决
skew join的打开方式:
#运行时
set hive.optimize.skewjoin=true;
#编译期
set hive.optimize.skewjoin.compiletime=true;
#开启union优化
set hive.optimize.union.remove=true;
skew join对于数据倾斜的解决方案就是单独开一个新的job,并对发生倾斜的数据进行map join。两个任务完成后使用union将结果进行拼接。