hive中的join相关的优化

1、Common join

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join.
整个过程包含Map、Shuffle、Reduce阶段。

Map阶段
读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;
Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表;
按照key进行排序

Shuffle阶段
根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中

Reduce阶段
根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

SELECT
a.id,a.dept,b.age
FROM a join b
ON (a.id = b.id);

图解上述示例

2、mapjoin(用于优化小表与大表join)

顾明思议,mapJoin的意思就是,当链接的两个表是一个比较小的表和一个特别大的表的时候,我们把比较小的table直接放到内存中去,然后再对比较大的表格进行map操作(执行mr过程的map操作)。join就发生在map操作的时候,每当扫描一个大的table中的数据,就要去去查看小表的数据,哪条与之相符,继而进行连接。这里的join会在map阶段完成,仅仅是在内存就进行了两个表的join,并不会涉及reduce操作。map端join的优势就是在于没有shuffle,从而提高效率。在实际的应用中,

实现mapjoin的方法1,hive自动识别

--默认值为true,自动开户MAPJOIN优化
set hive.auto.convert.join=true;
--默认值为2500000(25M),通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中
set hive.mapjoin.smalltable.filesize=2500000;

这样设置,hive就会自动的识别比较小的表,继而用mapJoin来实现两个表的联合。

实现mapjoin的方法2,可以自己指定

select /*+ mapjoin(a) */     --指定将a表放入内存中
        a.*,
        b.*
from table1 a join table12 b

3.Bucket-MapJoin (用于优化大表与大表join)

两个表join的时候,小表不足以放到内存中,但是又想用map side join这个时候就要用到bucket Map join。其方法是两个join表在join key上都做hash bucket,并且把你打算复制的那个(相对)小表的bucket数设置为大表的倍数。这样数据就会按照key join,做hash bucket。小表依然复制到所有节点,Map join的时候,小表的每一组bucket加载成hashtable,与对应的一个大表bucket做局部join,这样每次只需要加载部分hashtable就可以了。
前提条件

set hive.optimize.bucketmapjoin = true;
--一个表的bucket数是另一个表bucket数的整数倍
--列 == join列
--必须是应用在map join的场景中
--注意:如果表不是bucket的,则只是做普通join。

4、SMB Join(用于优化大表与大表join)

smb是sort  merge bucket操作是Bucket-MapJoin的优化,首先进行排序,继而合并,然后放到所对应的bucket中去,bucket是hive中和分区表类似的技术,就是按照key进行hash,相同的hash值都放到相同的buck中去。在进行两个表联合的时候。我们首先进行分桶,在join会大幅度的对性能进行优化。也就是说,在进行联合的时候,是table1中的一小部分和table1中的一小部分进行联合,table联合都是等值连接,相同的key都放到了同一个bucket中去了,那么在联合的时候就会大幅度的减小无关项的扫描。

进行相应的设置

--写入数据强制分桶
set hive.enforce.bucketing=true;
--写入数据强制排序
set hive.enforce.sorting=true;
--开启bucketmapjoin
set hive.optimize.bucketmapjoin = true;
--开启SMB Join
set hive.auto.convert.sortmerge.join=true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
--小表的bucket数=大表bucket数
--Bucket 列 == Join 列 == sort 列
--必须是应用在bucket mapjoin 的场景中

5、LEFT SEMI JOIN(代替 in)

LEFT SEMI JOIN 本质上就是 IN/EXISTS 子查询的表现,是IN的一种优化。

LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方都不行。

因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。这就导致右表有重复值得情况下 left semi join 只产生一条,join 会产生多条

left semi join 是只传递表的 join key 给 map 阶段,因此left semi join 中最后 select 的结果只许出现左表。因为右表只有 join key 参与关联计算了。

例子:存在俩个表t_user 表t_order 表

在这里插入图片描述     在这里插入图片描述

select
*
from t_user as t1
left join t_order as t2
on t1.user_id = t2.user_id;

结果如下:
在这里插入图片描述

select
*
from t_user as t1
left semi join t_order as t2
on t1.user_id = t2.user_id;

结果如下:

在这里插入图片描述

6、LEFT ANTI JOIN(代替 not in)

LEFT ANTI JOIN 本质上就是NOT IN/EXISTS 子查询的表现,是NOT IN的一种优化。

当on条件不成立时,才返回左表中的数据,保留在结果集中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值