hive中的join操作及其数据倾斜

时间:2024-06-03 07:49:43

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将结果进行拼接。

相关文章