MapJoin与ReduceJoin实例

本文详细介绍了MapJoin和ReduceJoin在大数据处理中的使用。MapJoin适用于小表与大表的联合,直接在Map阶段完成连接操作;而ReduceJoin适合处理两张大表的联合,通过定义Bean对象、Map和Reduce类实现。文中通过具体实例展示了两种方法的执行过程和结果,有助于理解这两种Join方法的工作原理。

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

产品表:
在这里插入图片描述
订单表:
在这里插入图片描述
需求:通过产品表和订单表得到,数据为(2019 01 小米 1)的表。

一、MapJoin

MapJoin适合小表+大表的联合。

1、Map类直接进行join操作

package com.join.mapjoin;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

public class MapJoin extends Mapper<LongWritable, Text, Text, NullWritable> {
   
   

    //定义HashMap对象存储小表对象
    HashMap hashMap = new HashMap<String, String>();

    /**
     * 将小表加载到内存中
     * @param context
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
   
   
        //获取缓存的文件
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Bigdata\\product.txt"), "UTF-8"));
        //按行读取数据
        String line;
        while (StringUtils.isNotEmpty(line=reader.readLine())){
   
   
            //切分小表行数据
            String[] split = line.split("\t");
            //数据存储进HashMap集合
            hashMap.put(split[0], split[1]);
        }
    }

    /**
     * Map方法
     * @param key
     * @param value
     * @param context
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
   
   
        //获取大表数据
        String line = value.toString();
        //切分
        String[] fields = line.split("\t");
        //按照productId关联
        String productId = fields[1];
        if (hashMap.containsKey(productId)) {
   
   
            context.write(new Text(fields[0].substring(0, 4) + "\t" + fields[0].substring(4)
                    + "\t" + hashMap.get(productId) + "\t" + fields[2]), NullWritable.get());
        }
    }

}

2、驱动程序

package com.join.mapjoin;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io
### Java中MapJoinReduceJoin的工作原理 #### MapJoin工作原理 在Java环境中实施MapJoin时,这种连接方式特别适合于一张表很大而另一张很小的情况。小表的数据会被完全加载至内存之中,在映射(Map)阶段执行连接操作。具体而言,通过分布式缓存(DistributedCache)[^3]机制将较小的表格预先分布到每一个Mapper节点上的本地磁盘空间内;当Mapper接收到来自大数据集的一条记录之后,会尝试将其已经存在于内存里的小型数据集合中的每一项进行匹配。一旦找到符合条件的关系,则立即生成相应的键值对作为中间输出的一部分。 对于Hive查询引擎,默认情况下已开启了自动识别并应用此策略的功能——即检测到存在大小差异明显的两张表参JOIN语句时便会启用MapJoin来加速整个过程[^2]。然而值得注意的是,即使采用了这样的优化手段,某些场景下仍然可能因为后续还需要聚合等其他类型的转换而导致部分任务不得不进入Reducer环节继续处理。 ```java // 小表预加载入全局变量或静态成员 static HashMap<String, String> smallTable; public static void main(String[] args){ // ... 初始化smallTable ... } @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); String bigTableRowKey = extractBigTablePrimaryKey(line); if (smallTable.containsKey(bigTableRowKey)) { // 执行连接逻辑并将结果写出 context.write(new Text(generateOutputKey()), new Text(generateOutputValue())); } } ``` #### ReduceJoin工作原理 相比之下,ReduceJoin并不依赖任何特殊的前提条件来进行优化设置。无论两份待联结的数据源规模如何,都会经历完整的MapReduce流程:先由Mappers负责初步解析输入文件并产出一系列<key,value>形式的基础单元供下游组件消费;随后这些散列化的片段被重新组合分配给多个Reducers实例共同承担起实际意义上的交叉参照职责。由于所有的比较动作都被集中安排到了最后一步骤里完成,因此不可避免地增加了单个Reduces所承受的压力以及整体作业所需耗费的时间成本。此外还容易引发诸如网络流量拥塞等问题的发生几率提升。 ```java @Override protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { List<String> listA = new ArrayList<>(); List<String> listB = new ArrayList<>(); for (Text val : values) { String originTableName = getOriginTableName(val); switch (originTableName) { case "table_a": listA.add(val.toString()); break; case "table_b": listB.add(val.toString()); break; } } // 对两个列表内的元素逐一配对检验是否存在交集关系 for (String aRow : listA) { for (String bRow : listB) { if (matchCondition(aRow, bRow)) { context.write(key, generateJoinedResult(aRow, bRow)); } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值