前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【大数据哔哔集20210117】Hive大表关联小表到底该怎么做

【大数据哔哔集20210117】Hive大表关联小表到底该怎么做

作者头像
大数据真好玩
发布2021-01-21 19:25:28
2.4K0
发布2021-01-21 19:25:28
举报
文章被收录于专栏:暴走大数据暴走大数据

在Hive调优里面,经常会遇到一个很小的表和一个大表进行Join,如何优化。

这时候就需要MAPJOIN。

原理

当一个大表和一个或多个小表做JOIN时,最好使用MAPJOIN,性能比普通的JOIN要快很多。另外,MAPJOIN 还能解决数据倾斜的问题。MAPJOIN的基本原理是:在小数据量情况下,SQL会将用户指定的小表全部加载到执行JOIN操作的程序的内存中,从而加快JOIN的执行速度。

样例:

代码语言:javascript
复制
select /*+MAPJOIN(b)*/ a.a1,a.a2,b.b2 from tablea a JOIN tableb b ON a.a1=b.b1

缓存多张小表:

代码语言:javascript
复制
select /*+MAPJOIN(b,c)*/ a.a1,a.a2,b.b2 from tablea a JOIN tableb b ON a.a1=b.b1 JOIN tbalec c on a.a1=c.c1

mapjoin的join发生在map阶段,join的join发生在reduce阶段,mapjoin可以提高效率。

使用方式

在Hive0.11前,必须使用MAPJOIN来标记显示地启动该优化操作,由于其需要将小表加载进内存所以要注意小表的大小。

代码语言:javascript
复制
SELECT /*+ MAPJOIN(smalltable)*/  .key,value
FROM smalltable JOIN bigtable ON smalltable.key = bigtable.key

在Hive0.11后,Hive默认启动该优化,也就是不在需要显示的使用MAPJOIN标记,其会在必要的时候触发该优化操作将普通JOIN转换成MapJoin,可以通过以下两个属性来设置该优化的触发时机

代码语言:javascript
复制
hive.auto.convert.join

默认值为true,自动开户MAPJOIN优化。

代码语言:javascript
复制
hive.mapjoin.smalltable.filesize

默认值为2500000(25M),通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中。

注意:使用默认启动该优化的方式如果出现默名奇妙的BUG(比如MAPJOIN并不起作用),就将以下两个属性置为fase手动使用MAPJOIN标记来启动该优化。

代码语言:javascript
复制
hive.auto.convert.join=false(关闭自动MAPJOIN转换操作)
hive.ignore.mapjoin.hint=false(不忽略MAPJOIN标记)

对于以下查询是不支持使用方法二(MAPJOIN标记)来启动该优化的

代码语言:javascript
复制
select /*+MAPJOIN(smallTableTwo)*/ idOne, idTwo, value FROM
  ( select /*+MAPJOIN(smallTableOne)*/ idOne, idTwo, value FROM
    bigTable JOIN smallTableOne on (bigTable.idOne = smallTableOne.idOne)                                                  
  ) firstjoin                                                            
  JOIN                                                                 
  smallTableTwo ON (firstjoin.idTwo = smallTableTwo.idTwo)

但是,如果使用的是方法一即没有MAPJOIN标记则以上查询语句将会被作为两个MJ执行,进一步的,如果预先知道表大小是能够被加载进内存的,则可以通过以下属性来将两个MJ合并成一个MJ。

代码语言:javascript
复制
hive.auto.convert.join.noconditionaltask:Hive在基于输入文件大小的前提下将普通JOIN转换成MapJoin,并是否将多个MJ合并成一个
hive.auto.convert.join.noconditionaltask.size:多个MJ合并成一个MJ时,其表的总的大小须小于该值,同时hive.auto.convert.join.noconditionaltask必须为true
MAPJOIN注意事项

当一个大表和一个或多个小表做JOIN时,最好使用MAPJOIN,性能比普通的JOIN要快很多。另外,MAPJOIN 还能解决数据倾斜的问题。MAPJOIN的基本原理是:在小数据量情况下,SQL会将用户指定的小表全部加载到执行JOIN操作的程序的内存中,从而加快JOIN的执行速度。使用MAPJOIN时,需要注意:

代码语言:javascript
复制
* LEFT OUTER JOIN的左表必须是大表;
* RIGHT OUTER JOIN的右表必须是大表;
* INNER JOIN左表或右表均可以作为大表;
* FULL OUTER JOIN不能使用MAPJOIN;
* MAPJOIN支持小表为子查询;
* 使用MAPJOIN时需要引用小表或是子查询时,需要引用别名;
* 在MAPJOIN中,可以使用不等值连接或者使用OR连接多个条件;
* 目前ODPS在MAPJOIN中最多支持指定6张小表,否则报语法错误;
* 如果使用MAPJOIN,则所有小表占用的内存总和不得超过512M(解压后的逻辑数据量)。

MAPJOIN 判定逻辑

代码语言:javascript
复制
同时满足下面2个条件:
1) Join阶段 max(join instance 运行时间) > 10分钟 && max( join instance 运行时间 ) > 2 * avg( join instance 运行时间 )
2) 参与join 的最小表数据量小于100M (解压前的逻辑数据量)

MAPJOIN 内存自定义设置

set odps.sql.mapjoin.memory.max=512 设置mapjoin时小表的最大内存,默认512,单位M,[128,2048]之间调整

案例

这个例子比较综合,既涉及到了数据倾斜问题,又涉及到当“小表”不是很小时(>512M)如何利用mapjoin。

代码语言:javascript
复制
select * from log a
  left outer join users b
  on a.user_id = b.user_id;

日志表(log)通常来说是记录数比较多的,但用户表(users)也不小,600W+ 的记录,把 users 分发到所有的 map 上也是个不小的开销,而且 map join 不支持这么大的小表。如果用普通的 join,又会碰到数据倾斜的问题。

代码语言:javascript
复制
  select /*+mapjoin(b)*/
  * 
  from log a
  left outer join (
    select  /*+mapjoin(c)*/
    d.*
    from ( select distinct user_id from log ) c
    join users d
    on c.user_id = d.user_id
    ) b
  on a.user_id = b.user_id;

这种解决方法的前提场景是:每日的会员uv不会太多,即 log 表中的 count(distinct user_id) 不会太大。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据真好玩 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理
  • 使用方式
  • MAPJOIN注意事项
  • 案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档