MapJoin 详细介绍

MapJoin详细介绍

1. 什么是MapJoin

MapJoin 是大数据处理框架如 Apache Hive 中的一种优化技术, 专门用于提升联接操作 (Join Operation) 的效率 ;

通常在处理海量数据时, 联接操作需要在两张或多张表直接匹配数据行, 这个过程可能会消耗大量的时间和资源 ;

MapJoin 提供了一种优化方案, 通过Map 阶段完成联接操作, 减少数据传输量和计算开销, 从而加快查询速度 ;

2. MapJoin 的工作原理

MapJoin 的关键思想是将小表加载到内存中, 并在 Map 阶段将它与大表进行联接 ; 它的工作原理可以分为以下几个步骤 :

  1. 识别小表: 在进行联接操作时, Hive 会自动或通过用户指定来识别那个表是’小表’, 即表的大小相对较小, 可以被加载到内存中 ;
  2. 将小表加载到内存: 在 Map 阶段开始前, 小表的所有内容会被加载到每个 Mapper 的内存中 ; 这使得 Mapper 在处理大表的每一条记录时, 都可以快速访问小表的数据 ;
  3. 在 Map 阶段进行联接: 每个 Mapper 通过将大表的记录与内存中的小表数据进行联接, 完成连接操作, 而无需等待 Shuffle 和 Reduce 阶段 ;
  4. 直接输出结果: 因为联接已经在 Map 阶段完成, 结果可以直接输出, 大大减少了 Shuffle 和 Reduce 阶段的工作量 ;
3. MapJoin 的优势
  • 减少网络传输: 传统的联接操作通常需要大量数据在不同节点间的传输, MapJoin 通过在 Map 阶段完成联接, 避免了这种网络开销 ;
  • 提高查询效率: 将联接提前至 Map 阶段, 直接输出结果, 避免了 Shuffle 和 Reduce 阶段的高昂计算和等待时间, 显著提高了查询的执行效率 ;
  • 适合小表联接大表: MapJoin 特别适合大表与小表的联接场景, 利用小表的内存加载特性, 可以极大优化这类操作 ;
4. 使用 MapJoin 的场景
  • 小表联接大表: 当其中一个表的体积非常小时, 可以使用 MapJoin 来加速联接 ;
  • 星型或雪花模型: 在数据仓库设计中, 事实表通常比较大, 而维表相对较小, 可以利用 MapJoin 优化查询性能 ;
  • 高并发查询环境: 在需要高并发、大吞吐量的数据查询场景下, MapJoin 能够有效减少资源消耗, 提高响应速度 ;
5. MapJoin 的配置

在Hive 中, MapJoin 可以通过以下几种方式进行配置 :

  1. 自动 MapJoin : Hive 默认会根据表的大小自动决定是否使用 MapJoin ; 可以通过设置 hive.auto.convert.join 参数为 true 来开启这个特性 ;
  2. 手动指定 MapJoin: 用户也可以在查询中手动指定使用 MapJoin , 例如通过在查询中使用 /*+mapjoin(tablename)*/ 来提示 Hive 将特定表加载到内存中 ;
  3. 内存限制: 为了防止内存不足导致任务失败, 可以通过设置 hive.mapjoin.localtask.max.memory.usage 参数来控制内存占用的比例 ;
6. MapJoin 注意事项
  • 内存消耗: 由于 MapJoin 需要将小表加载到每个 Mapper 的内存中, 因此在小表较大或 Mapper 数量较多时, 可能会消耗大量内存 ;
  • 小表选择: 选择不当的小表可能导致内存不足或性能下降, 因此在使用 MapJoin 时, 需要仔细评估小表的大小和内存占用 ;
7. 示例
-- 数据准备
-- 用户信息表
WITH user_info AS (
    SELECT * FROM (
      VALUES    (100, 18, 188),
                (101, 16, 182),
                (102, 26, 191),
                (103, 19, 186),
                (104, 22, 189)
    ) AS table_name(user_id, age, height)
)

-- 运动项目表(年龄要求范围)
, project_info AS (
    SELECT * FROM (
      VALUES    (2000, '篮球',   14, 17),
                (2001, '羽毛球', 14, 18),
                (2002, '长跑',   16, 20),
                (2003, '游泳',   16, 20),
                (2004, '射击',   16, 22),
                (2005, '跳高',   16, 18),
                (2006, '乒乓球', 14, 16)
    ) AS table_name(project_id, project_name, lower_age, upper_age)
)

-- 查看每个人员可以选择那些运动项目 (使用 mapjoin)
SELECT 
    /*+ mapjoin(b)*/
    user_id, age, height, project_id, project_name
FROM user_info a 
LEFT JOIN project_info b 
ON a.age BETWEEN lower_age AND upper_age
ORDER BY user_id
;
user_idageheightproject_idproject_name
100181882005跳高
100181882001羽毛球
100181882002长跑
100181882003游泳
100181882004射击
101161822001羽毛球
101161822002长跑
101161822000篮球
101161822003游泳
101161822006乒乓球
101161822004射击
101161822005跳高
10226191\N\N
103191862004射击
103191862003游泳
103191862002长跑
104221892004射击

在 MapJoin 中, 可以使用不等值联接或or联接多个条件 ;

MapJoin 中多个小表用英文逗号(,)分隔, 例如: /*+ mapjoin(b,c,d)*/ ;

8. 总结

MapJoin 是大数据处理框架中一个非常有效的优秀技术, 特别适用于大表与小表的联接操作 ;

通过小表加载到内存并在 Map 阶段完成联接, MapJoin 可以显著减少数据传输和计算开销, 从而加快查询执行速度 ;

在使用时, 合理配置和评估内存消耗是关键 ;

end
  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LambdaJoinQueryWrapper是MyBatis-Plus提供的一种查询构造器,用于实现多表关联查询,可以通过Lambda表达式来进行条件构造,支持LEFT JOIN、RIGHT JOIN、INNER JOIN等多种关联方式。 LambdaJoinQueryWrapper提供了join()方法来实现多表关联查询,可以通过传入Lambda表达式来构造关联条件。同时,LambdaJoinQueryWrapper还提供了select()、groupBy()、having()、orderBy()等方法来进行查询结果的筛选、分组、排序等操作。 使用LambdaJoinQueryWrapper的步骤如下: 1. 创建LambdaJoinQueryWrapper对象,指定主表实体类和表别名。 ``` LambdaJoinQueryWrapper<User> wrapper = new LambdaJoinQueryWrapper<>(User.class, "u"); ``` 2. 通过join()方法添加关联表和关联条件。 ``` wrapper.join(UserRole.class, ur -> ur.eq(UserRole::getUserId, User::getId)); ``` 3. 使用select()、groupBy()、having()、orderBy()等方法进行查询结果的筛选、分组、排序等操作。 ``` wrapper.select(User::getId, User::getUsername, avg(UserRole::getRoleId).as("roleAvg")) .groupBy(User::getId, User::getUsername) .having(avg(UserRole::getRoleId).gt(1)) .orderByDesc(User::getId); ``` 4. 最后使用MyBatis-Plus提供的selectList()、selectPage()、selectMaps()等方法进行查询操作。 ``` List<User> userList = userMapper.selectList(wrapper); Page<User> userPage = userMapper.selectPage(new Page<>(1, 10), wrapper); List<Map<String, Object>> userMapList = userMapper.selectMaps(wrapper); ``` LambdaJoinQueryWrapper可以大大简化多表关联查询的操作,减少手写SQL的工作量,提高代码的可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值