mr实现join的功能--Map端Join

大数据处理中绕不开的是两个甚至多个表的Join操作,由于要进行Shuffle操作,所以比较耗费时间,本文介绍了针对大小表Join的优化方法Map-Join,利用Hadoop提供的DistributedCache来进行缓存小表文件,然后再Mapper中直接进行Join,从而避免了Shuffle操作,加速了Join,具体实现可以看我的github

基础数据

有两张表,分别是用户信息数据以及用户页面的日志数据,建表语句如下所示:

-- 用户行为数据
CREATE TABLE `tmp.log_user_behavior`(
  `user_id` string COMMENT '用户id',
  `item_id` string COMMENT '商品id',
  `category_id` string COMMENT '商品分类id',
  `behavior` string COMMENT '行为',
  `ts` date COMMENT '行为发生时间')
PARTITIONED BY (
  `date` string)
  
231758,3622677,4758477,pv
92253,642337,4135185,pv
297958,1762578,4801426,pv
786771,1940649,1320293,pv
789048,3144191,2355072,pv
895384,1138468,1602288,pv
578800,1324176,4135836,pv
886777,4606952,996587,pv  

-- 用户信息
CREATE TABLE `tmp.base_user_info`(
  `user_id` string COMMENT '用户id',
  `user_name` string COMMENT '用户名字')
PARTITIONED BY (
  `date` string)

66985,name-66985
332113,name-332113
102932,name-102932
874086,name-874086

我们想要获取在用户行为信息上面添加上用户name信息,用sql实现如下:

select a.user_id, a.item_id, a.category_id, a.behavior, a.ts, b.user_name
from tmp.log_user_behavior a 
join tmp.base_user_info b 
on a.user_id = b.user_id
where a.date='20200831' and b.date='20200831'

本文从MR角度来实现Map端Join编程方法和思路。

Map端join

原理介绍

Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。

为了支持文件的复制,Hadoop提供了一个类DistributedCache,使用该类的方法如下:

  1. 用户使用静态方法DistributedCache.addCacheFile()指定要复制的文件,它的参数是文件的URI(如果是HDFS上的文件,可以这样:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口号)。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。
  2. 用户使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。

不过DistributedCache.addCacheFile()该方法在hadoop2.0之后的版本中已经废弃了,可以使用job.addCacheFile()方法添加缓存文件。

在hql里面相关配置如下:

set hive.auto.convert.join=true
set hive.mapjoin.smalltable.filesize=25000000

UserInfo实现

对于用户信息序列化处理

package com.hadoop.mapreduce.bean;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值