hadoop:join操作

一、 实验目的 1. 基于 MapReduce 思想,编写两文件 Join 操作的程序。
二、 实验要求 1. 能够理解 MapReduce 编程思想,然后会编写 MapReduce 版本 Join 程序,并能执 行该程序和分析执行过程。
三、 实验背景 1. 概述 对于 RDBMS 中的 Join 操作大伙一定非常熟悉,写 SQL 的时候要十分注意细节,稍 有差池就会耗时巨久造成很大的性能瓶颈,而在 Hadoop 中使用 MapReduce 框架进行 Join 的操作时同样耗时,但是由于 Hadoop 的分布式设计理念的特殊性,因此对于这种 Join 操作同样也具备了一定的特殊性。 2. 原理 使用 MapReduce 实现 Join 操作有多种实现方式: 在 Reduce 端连接为最为常见的模式: Map 端的主要工作:为来自不同表(文件)的 key/value 对打标签以区别不同来源的记 录。然后用连接字段作为 key,其余部分和新加的标志作为 value,最后进行输出。 Reduce 端的主要工作:在 Reduce 端以连接字段作为 key 的分组已经完成,我们只 需要在每一个分组当中将那些来源于不同文件的记录(在 map 阶段已经打标志)分开,最 后进行笛卡尔只就 OK 了。 在 Map 端进行连接使用场景:一张表十分小、一张表很大。 用法:在提交作业的时候先将小表文件放到该作业的 DistributedCache 中,然后从 DistributeCache 中取出该小表进行 Join key / value 解释分割放到内存中(可以放大 Hash Map 等等容器中)。然后扫描大表,看大表中的每条记录的 Join key /value 值是否能够在 内存中找到相同 Join key 的记录,如果有则直接输出结果。 SemiJoin SemiJoin 就是所谓的半连接,其实仔细一看就是 Reduce Join 的一个变种,就是在 map 端过滤掉一些数据,在网络中只传输参与连接的数据不参与连接的数据不必在网络 中进行传输,从而减少了 shuffle 的网络传输量,使整体效率得到提高,其他思想和 Reduce Join 是一模一样的。说得更加接地气一点就是将小表中参与 Join 的 key 单独抽出来通过 DistributedCach 分发到相关节点,然后将其取出放到内存中(可以放到 HashSet 中),在 map 阶段扫描连接表,将 Join key 不在内存 HashSet 中的记录过滤掉,让那些参与 Join 的记录通过 shuffle 传输到 Reduce 端进行 Join 操作,其他的和 Reduce Join 都是一样的
四、 实验步骤:
编写java代码:

package com.company;


import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.util.GenericOptionsParser;
 class MRJoin {
    public static class MR_Join_Mapper extends Mapper<LongWritable, Text, TextPair, Text> {
        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {
// 获取输入文件的全路径和名称
            String pathName = ((FileSplit) context.getInputSplit()).getPath(). toString();
            if (pathName.contains("data.txt")) {
                String values[] = value.toString().split("\t");
                if (values.length < 3) {
// data 数据格式不规范,字段小于 3,抛弃数据
                    return;
                } else {
// 数据格式规范,区分标识为 1
                    TextPair tp = new TextPair(new Text(values[1]), new Text("1"));
                    context.write(tp, new Text(values[0] + "\t" + values[2]));
                }
            }
            if (pathName.contains("info.txt")) {
                String values[] = value.toString().split("\t");
                if (values.length < 2) {// data 数据格式不规范,字段小于 2,抛弃数据
                    return;
                } else {
// 数据格式规范,区分标识为 0
                    TextPair tp = new TextPair(new
                            Text(values[0]), new Text("0"));
                    context.write(tp, new Text(values[1]));
                }
            }
        }
    }
    public static class MR_Join_Partitioner extends Partitioner<TextPair, Text> {
        @Override
        public int getPartition(TextPair key, Text value, int numParititon) {
            return Math.abs(key.getFirst().hashCode() * 127) % numParititon;
        }
    }
    public static class MR_Join_Comparator extends WritableComparator {
        public MR_Join_Comparator() {
            super(TextPair.class, true);
        }
        public int compare(WritableComparable a, WritableComparable b) {
            TextPair t1 = (TextPair) a;
            TextPair t2 = (TextPair) b;
            return t1.getFirst().compareTo(t2.getFirst());
        }
    }
    public static class MR_Join_Reduce extends Reducer<TextPair, Text, Text, Text> {protected void Reduce(TextPair key, Iterable<Text> values, Context
            context)
            throws IOException, InterruptedException {
        Text pid = key.getFirst();
        String desc = values.iterator().next().toString();
        while (values.iterator().hasNext()) {
            context.write(pid, new Text(values.iterator()
                    .next().toString() + "\t" + desc));
        }
    }
    }
    public static void main(String agrs[])
            throws IOException, InterruptedException, ClassNotFoundException {
        Configuration conf = new Configuration();
        GenericOptionsParser parser = new GenericOptionsParser(conf, agrs);
        String[] otherArgs = parser.getRemainingArgs();
        if (agrs.length < 3) {
            System.err.println("Usage: MRJoin <in_path_one> <in_path_two> <output>");
            System.exit(2);
        }
        Job job = new Job(conf, "MRJoin");
// 设置运行的 job
        job.setJarByClass(MRJoin.class);
// 设置 Map 相关内容
        job.setMapperClass(MR_Join_Mapper.class);
// 设置 Map 的输出
        job.setMapOutputKeyClass(TextPair.class);
        job.setMapOutputValueClass(Text.class);
// 设置 partition
        job.setPartitionerClass(MR_Join_Partitioner.class);
// 在分区之后按照指定的条件分组
        job.setGroupingComparatorClass(MR_Join_Comparator.class);
// 设置 Reduce
        job.setReducerClass(MR_Join_Reduce.class);
// 设置 Reduce 的输出
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);
// 设置输入和输出的目录
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileInputFormat.addInputPath(job, new Path(otherArgs[1]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[2]));
// 执行,直到结束就退出
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}
class TextPair implements WritableComparable<TextPair> {
    private Text first;
    private Text second;
    public TextPair() {
        set(new Text(), new Text());
    }
    public TextPair(String first, String second) {
        set(new Text(first), new Text(second));
    }
    public TextPair(Text first, Text second) {
        set(first, second);
    }public void set(Text first, Text second) {
        this.first = first;
        this.second = second;
    }
    public Text getFirst() {
        return first;
    }
    public Text getSecond() {
        return second;
    }
    public void write(DataOutput out) throws IOException {
        first.write(out);
        second.write(out);
    }
    public void readFields(DataInput in) throws IOException {
        first.readFields(in);
        second.readFields(in);
    }
    public int compareTo(TextPair tp) {
        int cmp = first.compareTo(tp.first);
        if (cmp != 0) {
            return cmp;
        }
        return second.compareTo(tp.second);
    }
}

#导入hadoop文件夹路径下的lib包。
1.点击file>Project Structure>Modules>+号>Library下的java找到你自己的lib文件然后ok。

2.打jar包
点击file>Project Structure>Artifacts>+号>jar找到rm的主类文件。

lib包的导入和jar的打包详情见上一个博客;
1:将打好的jar包更名为Mrjoin.jar 上传到hadoop中;
然后start-all.sh启动hadoop
2.创建hadoop fs -mkdir -p /datas/in , hadoop fs -mkdir -p /datas/out
在这里插入图片描述
3.编写data.txt和info.txt
然后用ftp传入hadoop中
5把上传到hadoop中的txt文档用hadoop fs -put data.txt /datas/in hadoop fs -put info.txt /datas/in上传到hdfs中
6.在你hadoop的jar包路径下执行
hadoop jar Mrjoin.jar /datas/in/data.txt info.txt /datas/out
在这里插入图片描述这样就完成了join操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值