Hadoop3:MapReduce中的Reduce Join和Map Join

一、概念说明

学过MySQL的都知道,join和left join
这里的join含义和MySQL的join含义一样
就是对两张表的数据,进行关联查询

Hadoop的MapReduce阶段,分为2个阶段
一个Map,一个Reduce
那么,join逻辑,就可以在这两个阶段实现。

两者有什么区别了?
我们都知道,一般情况下,MapTaskReduceTask线程数更多。
所以,当两张表,有一个表数据量非常大,一个表非常小的时候
我们建议放在Map阶段进行join,这样可以提高性能。

二、需求说明

有两张表数据
在这里插入图片描述
将商品信息表中数据根据商品pid合并到订单数据表中
在这里插入图片描述

三、代码实现

1、Reduce Join

TableBean

package com.atguigu.mapreduce.reduceJoin;import org.apache.hadoop.io.Writable;import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;public class TableBean implements Writable {private String id; // 订单idprivate String pid; // 商品idprivate int amount; // 商品数量private String pname;// 商品名称private String flag; // 标记是什么表 order pd// 空参构造public TableBean() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getPid() {return pid;}public void setPid(String pid) {this.pid = pid;}public int getAmount() {return amount;}public void setAmount(int amount) {this.amount = amount;}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname;}public String getFlag() {return flag;}public void setFlag(String flag) {this.flag = flag;}@Overridepublic void write(DataOutput out) throws IOException {out.writeUTF(id);out.writeUTF(pid);out.writeInt(amount);out.writeUTF(pname);out.writeUTF(flag);}@Overridepublic void readFields(DataInput in) throws IOException {this.id = in.readUTF();this.pid = in.readUTF();this.amount = in.readInt();this.pname = in.readUTF();this.flag = in.readUTF();}@Overridepublic String toString() {// id	pname	amountreturn  id + "\t" +  pname + "\t" + amount ;}
}

TableMapper
源数据,是多个文件的时候,我们要在setup方法里,获取文件信息
这样才能在map方法里知道,当前读取的是哪个文件,从而实现区别处理。

package com.atguigu.mapreduce.reduceJoin;import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;import java.io.IOException;public class TableMapper extends Mapper<LongWritable, Text, Text, TableBean> {private String fileName;private Text outK  = new Text();private TableBean outV = new TableBean();@Overrideprotected void setup(Context context) throws IOException, InterruptedException {// 初始化  order  pdFileSplit split = (FileSplit) context.getInputSplit();fileName = split.getPath().getName();}@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {// 1 获取一行String line = value.toString();// 2 判断是哪个文件的if (fileName.contains("order")){// 处理的是订单表String[] split = line.split("\t");// 封装k  voutK.set(split[1]);outV.setId(split[0]);outV.setPid(split[1]);outV.setAmount(Integer.parseInt(split[2]));outV.setPname("");outV.setFlag("order");}else {// 处理的是商品表String[] split = line.split("\t");outK.set(split[0]);outV.setId("");outV.setPid(split[0]);outV.setAmount(0);outV.setPname(split[1]);outV.setFlag("pd");}// 写出context.write(outK, outV);}
}

TableReducer

这里要注意
for循环处理bean list的时候,我们要在循环里面,new一个bean,存入list中
因为,Hadoop中,Iterable里存放的是地址,所以,不在循环内new一个bean来存放
会导致数据覆盖,最终只是存了一个bean

package com.atguigu.mapreduce.reduceJoin;import org.apache.commons.beanutils.BeanUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;public class TableReducer extends Reducer<Text, TableBean,TableBean, NullWritable> {@Overrideprotected void reduce(Text key, Iterable<TableBean> values, Context context) throws IOException, InterruptedException {
//        01 	1001	1   order
//        01 	1004	4   order
//        01	小米   	     pd// 准备初始化集合ArrayList<TableBean> orderBeans = new ArrayList<>();TableBean pdBean = new TableBean();// 循环遍历for (TableBean value : values) {if ("order".equals(value.getFlag())){// 订单表TableBean tmptableBean = new TableBean();try {BeanUtils.copyProperties(tmptableBean,value);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}orderBeans.add(tmptableBean);}else {// 商品表try {BeanUtils.copyProperties(pdBean,value);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}// 循环遍历orderBeans,赋值 pdnamefor (TableBean orderBean : orderBeans) {orderBean.setPname(pdBean.getPname());context.write(orderBean,NullWritable.get());}}
}

TableDriver

package com.atguigu.mapreduce.reduceJoin;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;public class TableDriver {public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {Job job = Job.getInstance(new Configuration());job.setJarByClass(TableDriver.class);job.setMapperClass(TableMapper.class);job.setReducerClass(TableReducer.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(TableBean.class);job.setOutputKeyClass(TableBean.class);job.setOutputValueClass(NullWritable.class);FileInputFormat.setInputPaths(job, new Path("E:\\workspace\\data\\inputtable"));FileOutputFormat.setOutputPath(job, new Path("E:\\workspace\\data\\join1"));boolean b = job.waitForCompletion(true);System.exit(b ? 0 : 1);}}

测试

在这里插入图片描述在这里插入图片描述

数据变化

1、源数据

在这里插入图片描述

2、Map方法中,按行读取数据

在这里插入图片描述

3、Shuffle阶段排序

因为,map方法中,用pid作为key,所以,这里对pid进行排序
在这里插入图片描述

4、Reduce方法,按key读取数据

这里的key只有3个,所以,reduce被调用了3次
每封装好一条数据,就write一次
reduce方法执行完毕后,进行归并排序,得到最终数据文件,输出到磁盘
在这里插入图片描述

2、Map Join

关键技术:
采用DistributedCache,在map阶段缓存小表数据
并且,取消reduce阶段

MapJoinDriver
关键代码:

        // 加载缓存数据job.addCacheFile(new URI("file:///D:/input/tablecache/pd.txt"));//缓存普通文件到Task运行节点。//job.addCacheFile(new URI("file:///e:/cache/pd.txt"));//如果是集群运行,需要设置HDFS路径//job.addCacheFile(new URI("hdfs://hadoop102:8020/cache/pd.txt"));// Map端Join的逻辑不需要Reduce阶段,设置reduceTask数量为0job.setNumReduceTasks(0);
package com.atguigu.mapreduce.mapjoin;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;public class MapJoinDriver {public static void main(String[] args) throws IOException, URISyntaxException, ClassNotFoundException, InterruptedException {// 1 获取job信息Configuration conf = new Configuration();Job job = Job.getInstance(conf);// 2 设置加载jar包路径job.setJarByClass(MapJoinDriver.class);// 3 关联mapperjob.setMapperClass(MapJoinMapper.class);// 4 设置Map输出KV类型job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(NullWritable.class);// 5 设置最终输出KV类型job.setOutputKeyClass(Text.class);job.setOutputValueClass(NullWritable.class);// 加载缓存数据job.addCacheFile(new URI("file:///D:/input/tablecache/pd.txt"));// Map端Join的逻辑不需要Reduce阶段,设置reduceTask数量为0job.setNumReduceTasks(0);// 6 设置输入输出路径FileInputFormat.setInputPaths(job, new Path("D:\\input\\inputtable2"));FileOutputFormat.setOutputPath(job, new Path("D:\\hadoop\\output8888"));// 7 提交boolean b = job.waitForCompletion(true);System.exit(b ? 0 : 1);}}

MapJoinMapper
setup方法中,使用driver中配置的小表文件路径,创建流,并将数据缓存起来,供map方法使用。

package com.atguigu.mapreduce.mapjoin;import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
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.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.HashMap;public class MapJoinMapper extends Mapper<LongWritable, Text, Text, NullWritable> {private HashMap<String, String> pdMap = new HashMap<>();private Text outK = new Text();@Overrideprotected void setup(Context context) throws IOException, InterruptedException {// 获取缓存的文件,并把文件内容封装到集合 pd.txtURI[] cacheFiles = context.getCacheFiles();FileSystem fs = FileSystem.get(context.getConfiguration());FSDataInputStream fis = fs.open(new Path(cacheFiles[0]));// 从流中读取数据BufferedReader reader = new BufferedReader(new InputStreamReader(fis, "UTF-8"));String line;while (StringUtils.isNotEmpty(line = reader.readLine())) {// 切割String[] fields = line.split("\t");// 赋值pdMap.put(fields[0], fields[1]);}// 关流IOUtils.closeStream(reader);}@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {// 处理 order.txtString line = value.toString();String[] fields = line.split("\t");// 获取pidString pname = pdMap.get(fields[1]);// 获取订单id 和订单数量// 封装outK.set(fields[0] + "\t" + pname + "\t" + fields[2]);context.write(outK, NullWritable.get());}
}

测试

在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/365947.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】和丰多媒体信息发布系统 QH.aspx 任意文件上传漏洞

0x01 产品简介 和丰多媒体信息发布系统也称数字标牌&#xff08;Digital Signage&#xff09;&#xff0c;是指通过大屏幕终端显示设备&#xff0c;发布商业、财经和娱乐信息的多媒体专业视听系统&#xff0c;常被称为除纸张媒体、电台、电视、互联网之外的“第五媒体”。该系…

第四节:如何使用注解方式从IOC中获取bean(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;上一节学习了如何理解Spring的两个特性IOC和AOP&#xff0c;这一节来基于上节的内容进行一个简单实践。这节要实现的效果是通过IOC容器获取到Bean&#xff0c;并且将Bean的属性显示打印出来。 第一步&#xff1a;创建pojo实体类stu…

MySQL 常见存储引擎详解(一)

本篇主要介绍MySQL中常见的存储引擎。 目录 一、InnoDB引擎 简介 特性 最佳实践 创建InnoDB 存储文件 二、MyISAM存储引擎 简介 特性 创建MyISAM表 存储文件 存储格式 静态格式 动态格式 压缩格式 三、MEMORY存储引擎 简介 特点 创建MEMORY表 存储文件 内…

AI智能剪辑发展到哪种地步?来看看云微客就知道了!

不是短视频团队招不起&#xff0c;而是矩阵账号更有性价比。企业做短视频有反思过为什么干不过同行吗&#xff1f;我们来看看大佬是怎么做的。云微客AI智能剪辑系统用几百个账号做矩阵布局&#xff0c;系统每天自动进行批量剪视频、写文案、一键自动化发布视频&#xff0c;一个…

RedHat9 | 内部YUM本地源服务器搭建

服务器参数 标识公司内部YUM服务器主机名yum-server网络信息192.168.37.1/24网络属性静态地址主要操作用户root 一、基础环境信息配置 修改主机名 [rootyum-server ~]# hostnamectl hostname yum-server添加网络信息 [rootyum-server ~]# nmcli connection modify ens160 …

Web2Code :网页理解和代码生成能力的评估框架

多模态大型语言模型&#xff08;MLLMs&#xff09;在过去几年中取得了爆炸性的增长。利用大型语言模型&#xff08;LLMs&#xff09;中丰富的常识知识&#xff0c;MLLMs在处理和推理各种模态&#xff08;如图像、视频和音频&#xff09;方面表现出色&#xff0c;涵盖了识别、推…

数据结构:队列详解 c++信息学奥赛基础知识讲解

目录 一、队列概念 二、队列容器 三、队列操作 四、代码实操 五、队列遍历 六、案例实操 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 详细代码&#xff1a; 一、队列概念 队列是一种特殊的线性…

量化交易 - 策略回测

策略回测 1、什么是策略回测&#xff1f;2、策略回测的作用3、策略回测系统概述3.1策略回测中相关的指标介绍3.2量化交易策略的资金容量3.3 完整的策略回测系统包含哪些内容 1、什么是策略回测&#xff1f; 策略回测&#xff0c;也称之为策略回溯测试&#xff0c;是指利用交易…

Sectigo或RapidSSL DV通配符SSL证书哪个性价比更高?

在当前的网络安全领域&#xff0c;选择一款合适的SSL证书对于保护网站和用户数据至关重要。Sectigo和RapidSSL作为市场上知名的SSL证书提供商&#xff0c;以其高性价比和快速的服务响应而受到市场的青睐。本文将对Sectigo和RapidSSL DV通配符证书进行深入对比&#xff0c;帮助用…

Cosine 余弦相似度并行计算的数学原理与Python实现

背景 Cosine 我在LLM与RAG系列课程已经讲了很多次了&#xff0c;这里不在熬述&#xff0c;它在LLM分析中&#xff0c;尤其是在语义相似度的计算中至关重要&#xff0c;在dot attention机制中&#xff0c;也会看到他的身影。这里讲的是纯数学上的运算与python是如何运用相关库进…

昇思25天学习打卡营第6天|网络构建

网络构建 概念模型模型参数 概念 神经网络模型是由神经网络层和Tensor操作构成的&#xff0c;mindspore.nn提供了常见神经网络层的实现&#xff0c;在MindSpore中&#xff0c;Cell类是构建所有网络的基类&#xff0c;也是网络的基本单元。一个神经网络模型表示为一个Cell&…

事务的特性-原子性(Atomicity)、一致性(Consistency)、隔离性(Asolation)、持久性(Durability)

一、引言 1、数据库管理系统DBMS为保证定义的事务是一个逻辑工作单元&#xff0c;达到引入事务的目的&#xff0c;实现的事务机制要保证事务具有原子性、一致性、隔离性和持久性&#xff0c;事务的这四个特性也统称为事务的ACID特性 2、当事务保持了ACID特性&#xff0c;才能…

Jasper studio报表工具中,如何判断subDataSource()子报表数据源是否为空

目录 1.1、错误描述 1.2、解决方案 1.1、错误描述 今天在处理一个有关Jasper Studio报表模板制作的线上问题&#xff0c;需要根据某个报表子数据源是否为空&#xff0c;来决定对应的组件是否显示&#xff0c;找了好久的资料都没有实现&#xff0c;最后找到一种解决办法。就是…

【Mybatis 与 Spring】事务相关汇总

之前分享的几篇文章可以一起看&#xff0c;形成一个体系 【Mybatis】一级缓存与二级缓存源码分析与自定义二级缓存 【Spring】Spring事务相关源码分析 【Mybatis】Mybatis数据源与事务源码分析 Spring与Mybaitis融合 SpringManagedTransaction&#xff1a; org.mybatis.spri…

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数 0. 引言1. 关于m_pcolor2. 关于m_image3. 关于m_shadedrelief4. 关于m_hatch5. 结语 0. 引言 本篇介绍下m_map中区域填充函数&#xff08;m_hatch&#xff09;、绘制伪彩色图…

Coze搭建《测测你的本命宠物》

前言 本文讲解如何从零开始&#xff0c;使用扣子平台去搭建《测测你的本命宠物》 《测测你的本命宠物》&#xff1a;测测你的本命宠物 - 扣子 AI Bot (coze.cn) 欢迎大家去体验一下&#xff01;&#xff01;&#xff01; 正文 接下来我们开始讲解制作这个bot的流程吧&#…

公网环境使用Potplayer远程访问家中群晖NAS搭建的WebDAV听歌看电影

文章目录 前言1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav4 内网穿透&#xff0c;映射至公网5 使用固定地址在potplayer访问webdav 前言 本文主要介绍如何在Windows设备使用potplayer播放器远程访问本地局域网的群晖NAS中的影视资源&#xff…

解析 Ferret-UI:多模态大模型在移动用户界面理解中的应用

移动应用的爆炸性增长&#xff0c;用户界面&#xff08;UI&#xff09;的设计越来越复杂&#xff0c;功能也越来越丰富。但现有的多模态大模型&#xff08;MLLMs&#xff09;在理解用户界面时存在局限&#xff0c;尤其是在处理具有特定分辨率和包含众多小型对象&#xff08;如图…

debian打包小结

背景 业务需要&#xff0c;打一个openstack组件的deb包 openstack组件有setup.py可直接支持打rpm包&#xff0c;但不支持deb包&#xff0c;所以手动打deb包 用了dh_make准备打包文件&#xff0c;然后用debuild或dpkg-buildpackages打deb包 步骤 方法有很多&#xff0c;我用…

【uniapp】HBuilderx中uniapp项目运行到微信小程序报错Error: Fail to open IDE

HBuilderx中uniapp项目运行到微信小程序报错Error: Fail to open IDE 问题描述 uniapp开发微信小程序&#xff0c;在HBuilderx中运行到微信开发者工具时报错Error: Fail to open IDE 解决方案 1. 查看微信开发者工具端服务端口是否开放 打开微信开发者工具选择&#xff1…