hive中的mapjoin

本文介绍如何在Hive中通过调整配置参数实现MapJoin优化,针对一张大表关联多张小表的情况,通过设置`hive.auto.convert.join`等参数,自动转换为MapJoin加速查询过程。详细阐述了MapJoin的工作原理及参数作用,包括小表文件大小限制、合并MapJoin的好处和限制条件,以及如何通过`explain`命令验证效果。同时,文章强调了使用MapJoin时关联字段类型的一致性要求,并分享了一个关于字段类型不一致导致性能下降的案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Hive中,common join是很慢的,如果我们是一张大表关联多张小表,可以使用mapjoin加快速度。
mapjoin主要有以下参数:

  • hive.auto.convert.join : 是否自动转换为mapjoin
  • hive.mapjoin.smalltable.filesize : 小表的最大文件大小,默认为25000000,即25M
  • hive.auto.convert.join.noconditionaltask : 是否将多个mapjoin合并为一个
  • hive.auto.convert.join.noconditionaltask.size : 多个mapjoin转换为1个时,所有小表的文件大小总和的最大值。

例如,一个大表顺序关联3个小表a(10M), b(8M),c(12M),如果hive.auto.convert.join.noconditionaltask.size的值:

1. 小于18M,则无法合并mapjoin,必须执行3个mapjoin;

2. 大于18M小于30M,则可以合并a和b表的mapjoin,所以只需要执行2个mapjoin;
3. 大于30M,则可以将3个mapjoin都合并为1个。

合并mapjoin有啥好处呢?因为每个mapjoin都要执行一次map,需要读写一次数据,所以多个mapjoin就要做多次的数据读写,合并mapjoin后只用读写一次,自然能大大加快速度。但是执行map是内存大小是有限制的,在一次map里对多个小表做mapjoin就必须把多个小表都加入内存,为了防止内存溢出,所以加了hive.auto.convert.join.noconditionaltask.size参数来做限制。不过,这个值只是限制输入的表文件的大小,并不代表实际mapjoin时hashtable的大小。
我们可以通过explain查看执行计划,来看看mapjoin是否生效。

具体示例

set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=300000000;
set hive.auto.convert.join.noconditionaltask=true;
set hive.auto.convert.join.noconditionaltask.size=300000000;

使用mapjoin时,会先执行一个本地任务(mapreduce local task)将小表转成hashtable并序列化为文件再压缩,随后这些hashtable文件会被上传到hadoop缓存,提供给各个mapjoin使用。这里有三个参数我们需要注意:

  • hive.mapjoin.localtask.max.memory.usage : 将小表转成hashtable的本地任务的最大内存使用率,默认0.9
  • hive.mapjoin.followby.gby.localtask.max.memory.usage : 如果mapjoin后面紧跟着一个group by任务,这种情况下 本地任务的最大内存使用率,默认是0.55
  • hive.mapjoin.check.memory.rows : localtask每处理完多少行,就执行内存检查。默认为100000

如果我们的localtask的内存使用超过阀值,任务会直接失败。

此外,使用mapjoin时还要注意,用作join的关联字段的字段类型最好要一致。
我就碰到一个诡异的问题,执行mapjoin 的local task时一直卡住,40万行的小表处理了好几个小时,正常情况下应该几秒钟就完成了。查了好久原因,结果原来是做join的关联字段的类型不一致,一边是int, 一边是string,hive解释计划里显示它们都会被转成double再来join。我把字段类型改为一致的,瞬间就快了。照理说就算转成double也不该这么慢,不知道是不是hive的bug。

说明:本人使用的是hive 1.2.1

参考文档
hive配置属性https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+JoinOptimization
https://cwiki.apache.org/confluence/display/Hive/MapJoinOptimization
https://cwiki.apache.org/confluence/display/Hive/MapJoin+and+Partition+Pruning

Hive中的Map Join是一种优化技术,用于在执行连接操作时减少数据倾斜和提高查询性能。Map Join通过在Map阶段完成连接操作,避免了Reducer阶段的处理,从而加快了查询速度。 ### 开启Map Join的方法 1. **自动Map Join**: Hive可以根据查询的实际情况自动选择使用Map Join。可以通过设置以下参数来启用自动Map Join: ```sql set hive.auto.convert.join=true; set hive.auto.convert.join.noconditionaltask=true; set hive.auto.convert.join.noconditionaltask.size=10000000; -- 设置小表的最字节数 ``` 2. **手动Map Join**: 可以在SQL查询中使用提示(Hint)来手动指定Map Join。语法如下: ```sql SELECT /*+ MAPJOIN(table_name) */ columns FROM table1 JOIN table2 ON table1.column = table2.column; ``` ### 注意事项 - **小表小**:Map Join适用于小表之间的连接操作。小表小应小于`hive.auto.convert.join.noconditionaltask.size`参数设置的值。 - **资源消耗**:Map Join会将小表的数据加载到内存中,因此需要确保集群有足够的内存资源。 ### 示例 假设我们有两个`orders`和`customers`,其中`customers`小表,我们可以使用Map Join来优化连接操作: ```sql set hive.auto.convert.join=true; set hive.auto.convert.join.noconditionaltask=true; set hive.auto.convert.join.noconditionaltask.size=10000000; SELECT /*+ MAPJOIN(customers) */ o.order_id, c.customer_name FROM orders o JOIN customers c ON o.customer_id = c.customer_id; ``` 在上述示例中,`customers`被标记为Map Join的小表Hive会在Map阶段完成连接操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值