MAPJOIN
当一个大表和一个或多个小表做JOIN时,最好使用MAPJOIN,性能比普通的JOIN要快很多。 另外,MAPJOIN 还能解决数据倾斜的问题。
MAPJOIN的基本原理是:在小数据量情况下,SQL会将用户指定的小表全部加载到执行JOIN操作的程序的内存中,从而加快JOIN的执行速度。
使用MAPJOIN时,需要注意:
- LEFT OUTER JOIN的左表必须是大表;
- RIGHT OUTER JOIN的右表必须是大表;
- INNER JOIN左表或右表均可以作为大表;
- FULL OUTER JOIN不能使用MAPJOIN;
- MAPJOIN支持小表为子查询;
- 使用MAPJOIN时需要引用小表或是子查询时,需要引用别名;
- 在MAPJOIN中,可以使用不等值连接或者使用OR连接多个条件;
- 目前ODPS在MAPJOIN中最多支持指定6张小表,否则报语法错误;
- 如果使用MAPJOIN,则所有小表占用的内存总和不得超过512M(解压后的逻辑数据量)。
MAPJOIN 判定逻辑:
同时满足下面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.
场景:select * from log a left outer join users b on a.user_id = b.user_id;
日志表(log)通常来说是记录数比较多的,但用户表(users)也不小,600W+ 的记录,把 users 分发到所有的 map 上也是个不小的开销,而且 map join 不支持这么大的小表。如果用普通的 join,又会碰到数据倾斜的问题。
解决方法: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) 不会太大。
华北2(北京)Region MaxCompute购买地址:https://common-buy.aliyun.com/?commodityCode=odpsplus#/buy
欢迎加入“数加·MaxCompute购买咨询”钉钉群(群号: 11782920)进行咨询,群二维码如下: