如何使用MapReduce实现两表的join

map join:
map side join 是针对一下场景进行的优化。两个待连接的表中,有一个表非常大,而另一个非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每一个map task内存中存在一份(比如放在hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否具有相同key的记录,入股有,则连接后输出即可。
场景:MapJoin 适用于有一份数据较小的连接情况。
做法:直接将较小的数据加载到内存中,按照连接的关键字建立索引,大份数据作为MapTask的输入数据对 map()方法的每次输入都去内存当中直接去匹配连接。然后把连接结果按 key 输出,这种方法要使用 hadoop中的 DistributedCache 把小份数据分布到各个计算节点,每个 maptask 执行任务的节点都需要加载该数据到内存,并且按连接关键字建立索引。

reduce join
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源key/value数据对,没条数据打一个标签(tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。

在map阶段, 把关键字作为key输出,并在value中标记出数据是来自data1还是data2。因为在shuffle阶段已经自然按key分组,reduce阶段,判断每一个value是来自data1还是data2,在内部分成2组,做集合的乘积。
这种方法有2个问题:
map阶段没有对数据瘦身,shuffle的网络传输和排序性能很低。
reduce端对2个集合做乘积计算,很耗内存,容易导致OOM。

MapReduce实现两个join 操作通常需要以下步骤: 1. Mapper 阶段:将两个中需要进行 join 的列作为 key,将整行数据作为 value 发送给 reduce 阶段。需要注意的是,对于需要 join 的列,需要在 Mapper 中进行标记。 2. Partitioner 阶段:将 Mapper 阶段输出的数据按照 key 进行分区,使得同一个 key 的数据被分配到同一个 reduce task 中。 3. Sort/Shuffle 阶段:对于每个 reduce task,将其对应的数据按照 key 进行排序,使得同一个 key 的数据排在一起。 4. Reducer 阶段:对于每个 key,将其对应的两个的数据进行合并,并将结果输出。 以下是一个示例代码: ```java public class JoinMapper extends Mapper<LongWritable, Text, Text, Text> { private Text joinKey = new Text(); private Text joinValue = new Text(); protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] fields = value.toString().split("\t"); String joinColumnName = "join_column_name"; String tableIndicator = fields[0]; if (tableIndicator.equals("table1")) { joinKey.set(fields[1]); joinValue.set(joinColumnName + "\t" + fields[2]); context.write(joinKey, joinValue); } else if (tableIndicator.equals("table2")) { joinKey.set(fields[2]); joinValue.set(joinColumnName + "\t" + fields[1]); context.write(joinKey, joinValue); } } } public class JoinReducer extends Reducer<Text, Text, Text, Text> { private Text outputValue = new Text(); protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { String joinColumnName = "join_column_name"; String table1Value = null; String table2Value = null; for (Text value : values) { String[] fields = value.toString().split("\t"); if (fields[0].equals(joinColumnName)) { if (table1Value == null) { table1Value = fields[1]; } else { table2Value = fields[1]; } } } if (table1Value != null && table2Value != null) { outputValue.set(table1Value + "\t" + table2Value); context.write(key, outputValue); } } } ``` 在上述示例中,我们假设有两个,分别为 table1 和 table2,需要按照它们的某一列进行 join 操作。Mapper 阶段将需要 join 的列作为 key,将整行数据作为 value 发送给 reduce 阶段;Partitioner 阶段按照 key 进行分区;Sort/Shuffle 阶段对于每个 reduce task,将其对应的数据按照 key 进行排序;Reducer 阶段对于每个 key,将其对应的两个的数据进行合并,并将结果输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值