如何优化Hive Join:提升大数据查询效率的实战技巧

如何优化Hive Join:提升大数据查询效率的实战技巧

1.1 JOIN 优化

JOIN 是数据分析处理过程中必不可少的操作,Hive 同样支持 JOIN 的语法。而 Hive JOIN 的底层是通过 MapReduce 来

实现的,Hive 实现 JOIN 时,为了提高 MapReduce 的性能,提供了多种 JOIN 方案:

  • 小表 JOIN 大表的 Map Join

  • 大表 JOIN 大表的 Reduce Join,Reduce Join 又分为以下两种:

    • Bucket Map Join(中型表和大表 JOIN)

    • Sort Merge Bucket Join(大表和大表 JOIN)

2.2 Map Join

Map Join 顾名思义,就是在 Map 阶段进行表之间的连接。而不需要进入到 Reduce 阶段才进行连接。这样就节省了

在 Shuffle 阶段时要进行的大量数据传输。从而起到了优化作业的作用。

Map Join 简单说就是在 Map 阶段将小表读入内存,顺序扫描大表完成 Join。

在这里插入图片描述

上图是 Hive MapJoin 的原理图,出自 Facebook 工程师 Liyin Tang 的一篇介绍 Join 优化的文章,从图中可以看出

MapJoin 分为两个阶段:

  • 通过 MapReduce Local Task 将小表读入内存,生成 HashTableFiles 上传至 Distributed Cache 中,这里会对HashTableFiles 进行压缩。

  • MapReduce Job 在 Map 阶段,每个 Mapper 从 Distributed Cache 读取 HashTableFiles 到内存中,顺序扫描大表,在

    Map 阶段直接进行 Join,将数据传递给下一个 MapReduce 任务。

应用场景:小表 JOIN 大表或者小表 JOIN 小表。

实现原理:Map Join 会把小表全部读入内存中,在 Map 阶段直接拿另外一个表的数据和内存中的表数据做匹配,由

于在 Map 阶段进行了 JOIN 操作,底层不需要经过 Shuffle,这样就不会由于数据倾斜导致某个 Reduce 上落数据太多而失

败,但是需要占用内存空间存放小表数据。

具体使用:尽量使用 Map Join 来实现 JOIN 过程,Hive 中默认开启了 Map Join:

-- 是否开启 Map Join,默认为 true
SET hive.auto.convert.join=true;
-- 2.0 版本之前的控制参数
-- 如果打开上面这个参数,当参与 Join 的表小于下面参数指定的值,将转换为 Map Join,默认为 25000000
SET hive.mapjoin.smalltable.filesize=25000000;
-- 2.0 版本开始由以下参数控制
-- 是否启用基于输入文件的大小,将 Reduce Join 转化为 Map Join,默认为 true
SET hive.auto.convert.join.noconditionaltask=true;
-- 假设参与 Join 的表(或分区)有 N 个,如果打开上面这个参数,并且有 N-1 个表(或分区)的大小总和小于下面参数指定
的值,那么会直接将 Join 转为 Map Join,默认为 10000000
SET hive.auto.convert.join.noconditionaltask.size=10000000;
-- 注意:量变引起质变,在量少的情况下是优化的操作,等到量大时没准就会出问题,所以性能优化不是一成不变的,需要具
体情况具体分析。例如好友推荐案例的分析结果。

使用优化的 Map Join 过程中没有 Shuffle 是通过本地的一个 HashTable 较小的表(较小的表的识别可以通过元数据信

息判断)生成 HashTable Files 文件,并保存到 HDFS 的临时缓存当中,然后通过与 Map 出来的另一个表进行直接匹配,得

出结果,因此过程中没有 Shuffle,不需要网络,所以效率相对来说较快,即为优化。例如:

EXPLAIN EXTENDED SELECT E.EMPNO,E.SAL,D.DEPTNO FROM EMP E JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
-- 在执行计划中可以看到关于 HashTable 的操作
HashTable Sink Operator

3.3 Reduce Join

Map 端的主要工作:为来自不同表或文件的 key/value 对,打标签以区别不同来源的记录。然后用连接字段作为

Key,其余部分和新加的标志作为 Value,最后进行输出。

Reduce 端的主要工作:在 Reduce 端以连接字段作为 Key 的分组已经完成,我们只需要在每一个分组当中将那些来源

于不同文件的记录进行合并即可

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/f3aecb63c2304912b6575c13fee2167e.png)

应用场景:大表 JOIN 大表。

实现原理:将两张表的数据在 Shuffle 阶段利用 Shuffle 的分组将数据按照关联字段进行合并。

具体使用:Hive 会自动判断是否满足 Map Join,如果不满足 Map Join,则会自动执行 Reduce Join。

3.3.1 Bucket Map Join

大表对小表应该使用 Map Join 来进行优化,但是如果是大表对大表,如果进行 Shuffle,那就非常可怕,第一个慢不

用说,第二个容易出异常。此时就可以使用 Bucket Join 来进行优化,而 Bucket Join 又分为:

  • Bucket Map Join
  • Sort Merge Bucket Join(SMB Join)

具体使用流程如下:

  • 将两张大表的数据构建分桶

  • 数据按照分桶的规则拆分到不同的文件中

    • 分桶规则 = MapReduce 分区的规则 = Key 的 Hash 取余

    • Key = 分桶的字段

  • 只需要实现桶与桶的 JOIN 即可,减少了比较次数

分桶本质:底层 MapReduce 的分区,桶的个数 = Reduce 个数 = 文件个数

在这里插入图片描述

​ 两张表 JOIN 的时候,小表不足以放到内存中,但是又想用 Map Join,这个时候就要用到 Bucket Map Join。其方法是

两个 JOIN 表都在 Join Key上都做 Hash Bucket,并且把你打算复制的那个(相对)小表的 Bucket 数设置为大表的倍数。这

样数据就会按照 Key Join 做 Hash Bucket。小表依然复制到所有节点,Map Join 的时候,小表的每一组 Bucket 加载成

HashTable,与对应的一个大表 Bucket 做局部 JOIN,这样每次只需要加载部分 HashTable 就可以了。

Map Join 条件:

  • SET hive.optimize.bucketmapjoin=true; ,默认为 false
  • 所有要 JOIN 的表必须分桶,如果表不是 Bucket 的,则只是做普通 JOIN
  • 大表的 Bucket 数是小表的 Bucket 数的整数倍(或相等)
  • Bucket 列 == JOIN 列
  • 必须是应用在 Map Join 的场景中

3.4 SMB Join

在这里插入图片描述

​ SMB Join 是基于 Bucket Map Join 的有序 Bucket,可实现在 Map 端完成 JOIN 操作,只要桶内的下一条不是,就不用

再比较了,有效地减少或避免 Shuffle 的数据量。

SMB Join 的条件和 Map Join 类似但又不同:

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;
  • 所有要 JOIN 的表必须分桶,如果表不是 Bucket 的,则只是做普通 JOIN
  • 大表的 Bucket 数 = 大表的 Bucket 数
  • Bucket 列 == JOIN 列 == SORT 列
    ve.auto.convert.sortmerge.join.noconditionaltask=true;

- 所有要 JOIN 的表必须分桶,如果表不是 Bucket 的,则只是做普通 JOIN
- 大表的 Bucket 数 = 大表的 Bucket 数
- Bucket 列 == JOIN 列 == SORT 列
- 必须是应用在 Bucket Map Join 的场景中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值