张表,分别较data.txt和info.txt,字段之间以/t划分。

data.txt内容如下:

201001    1003    abc

201002    1005    def

201003    1006    ghi

201004    1003    jkl

201005    1004    mno

201006    1005    pqr

info.txt内容如下:

1003    kaka

1004    da

1005    jue

1006    zhao

期望输出结果:

1003    201001    abc    kaka

1003    201004    jkl    kaka

1004    201005    mno    da

1005    201002    def    jue

1005    201006    pqr    jue

1006    201003    ghi    zhao

四、Map代码

首先是map的代码,我贴上,然后简要说说

public static class Example_Join_01_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]));

}

}

}

}

这里需要注意以下部分:

A、pathName是文件在HDFS中的全路径(例如:hdfs://M1:9000/MengYan/join/data/info.txt),可以以endsWith()的方法来判断。

B、资料表,也就是这里的info.txt需要放在前面,也就是标识号是0.否则无法输出理想结果。

C、Map执行完成之后,输出的中间结果如下:

1003,0    kaka

1004,0    da

1005,0    jue

1006,0    zhao

1003,1    201001    abc

1003,1    201004    jkl

1004,1    201005    mon

1005,1    201002    def

1005,1    201006    pqr

1006,1    201003    ghi

五、分区和分组

、map之后的输出会进行一些分区的操作,代码贴出来:

public static class Example_Join_01_Partitioner extends Partitioner<TextPair, Text> {

@Override

public int getPartition(TextPair key, Text value, int numParititon) {

return Math.abs(key.getFirst().hashCode() * 127) % numParititon;

}

}

,那么就是分区有多个,但是还是在一个reduce中处理。但是结果会按照分区的原则排序)。分区后结果大致如下:

同一区:

1003,0    kaka

1003,1    201001    abc

1003,1    201004    jkl

同一区:

1004,0    da

1004,1    201005    mon

同一区:

1005,0    jue

1005,1    201002    def

1005,1    201006    pqr

同一区:

1006,0    zhao

1006,1    201003    ghi

、分组操作,代码如下

public static class Example_Join_01_Comparator extends WritableComparator {

public Example_Join_01_Comparator() {

super(TextPair.class, true);

}

@SuppressWarnings("unchecked")

public int compare(WritableComparable a, WritableComparable b) {

TextPair t1 = (TextPair) a;

TextPair t2 = (TextPair) b;

return t1.getFirst().compareTo(t2.getFirst());

}

}

分组操作就是把在相同分区的数据按照指定的规则进行分组的操作,就以上来看,是按照复合key的第一个字段做分组原则,达到忽略复合key的第二个字段值的目的,从而让数据能够迭代在一个reduce中。输出后结果如下:

同一组:

1003,0    kaka

1003,0    201001    abc

1003,0    201004    jkl

同一组:

1004,0    da

1004,0    201005    mon

同一组:

1005,0    jue

1005,0    201002    def

1005,0    201006    pqr

同一组:

1006,0    zhao

1006,0    201003    ghi

六、reduce操作

贴上代码如下:

public static class Example_Join_01_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));

}

}

}

、代码比较简单,首先获取关键的ID值,就是key的第一个字段。

、获取公用的字段,通过排组织后可以看到,一些共有字段是在第一位,取出来即可。

、遍历余下的结果,输出。

七、其他的支撑代码

、首先是TextPair代码,没有什么可以细说的,贴出来:

public 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);

}

}

、Job的入口函数

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: Example_Join_01 <in_path_one> <in_path_two> <output>");

System.exit(2);

}

//conf.set("hadoop.job.ugi", "root,hadoop");

Job job = new Job(conf, "Example_Join_01");

// 设置运行的job

job.setJarByClass(Example_Join_01.class);

// 设置Map相关内容

job.setMapperClass(Example_Join_01_Mapper.class);

// 设置Map的输出

job.setMapOutputKeyClass(TextPair.class);

job.setMapOutputValueClass(Text.class);

// 设置partition

job.setPartitionerClass(Example_Join_01_Partitioner.class);

// 在分区之后按照指定的条件分组

job.setGroupingComparatorClass(Example_Join_01_Comparator.class);

// 设置reduce

job.setReducerClass(Example_Join_01_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);

}

八、总结

、这是个简单的join查询,可以看到,我在处理输入源的时候是在map端做来源判断。其实在0.19可以用MultipleInputs.addInputPath()的方法,但是它用了JobConf做参数。这个方法原理是多个数据源就采用多个map来处理。方法各有优劣。

、对于资源表,如果我们采用0和1这样的模式来区分,资源表是需要放在前的。例如本例中info.txt就是资源表,所以标识位就是0.如果写为1的话,可以试下,在分组之后,资源表对应的值放在了迭代器最后一位,无法追加在最后所有的结果集合中。

、关于分区,并不是所有的map都结束才开始的,一部分数据完成就会开始执行。同样,分组操作在一个分区内执行,如果分区完成,分组将会开始执行,也不是等所有分区完成才开始做分组的操作。

Map/Reduce中Join查询实现的更多相关文章

  1. Map Reduce Application(Join)

    We are going to explain how join works in MR , we will focus on reduce side join and map side join. ...

  2. Hive 中Join的专题---Join详解

    1.什么是等值连接? 2.hive转换多表join时,如果每个表在join字句中,使用的都是同一个列,该如何处理? 3.LEFT,RIGHT,FULL OUTER连接的作用是什么? 4.LEFT或RI ...

  3. Map/Reduce之间的Partitioner接口

    一.Partitioner介绍 Partitioner的作用是对Mapper产生的中间结果进行分片,以便将同一分组的数据交给同一个Reduce处理,它直接影响Reduce阶段的负载均衡(个人理解:就是 ...

  4. mapreduce: 揭秘InputFormat--掌控Map Reduce任务执行的利器

    随着越来越多的公司采用Hadoop,它所处理的问题类型也变得愈发多元化.随着Hadoop适用场景数量的不断膨胀,控制好怎样执行以及何处执行map任务显得至关重要.实现这种控制的方法之一就是自定义Inp ...

  5. Map Reduce和流处理

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由@从流域到海域翻译,发表于腾讯云+社区 map()和reduce()是在集群式设备上用来做大规模数据处理的方法,用户定义一个特定的映射 ...

  6. Hadoop学习笔记2 - 第一和第二个Map Reduce程序

    转载请标注原链接http://www.cnblogs.com/xczyd/p/8608906.html 在Hdfs学习笔记1 - 使用Java API访问远程hdfs集群中,我们已经可以完成了访问hd ...

  7. 入门大数据---Map/Reduce,Yarn是什么?

    简单概括:Map/Reduce是分布式离线处理的一个框架. Yarn是Map/Reduce中的一个资源管理器. 一.图形说明下Map/Reduce结构: 官方示意图: 另外还可以参考这个: 流程介绍: ...

  8. hadoop 多表join:Map side join及Reduce side join范例

    最近在准备抽取数据的工作.有一个id集合200多M,要从另一个500GB的数据集合中抽取出所有id集合中包含的数据集.id数据集合中每一个行就是一个id的字符串(Reduce side join要在每 ...

  9. hadoop的压缩解压缩,reduce端join,map端join

    hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...

随机推荐

  1. flex 4 布局样式

    Flex 4 样式与布局 第一篇 Flex 4 与自定义布局(Layout) Flex 4/Spark组件架构的新功能之一是可以定制一个容器的布局而不必改变容器本身.您需要做的就是定义一个自定义布局. ...

  2. Using Git subtrees to split a repository

    https://lostechies.com/johnteague/2014/04/04/using-git-subtrees-to-split-a-repository/ We are in a p ...

  3. [Golang] base64加密与解密

    首先解释以下什么是base64(来自百度百科): Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的详细规范.Base64 ...

  4. LCS记录路径

    还想用hash记录……果然是天真.lcs转移比较简单,每次增加1.每次找是当前-1的就行了. #include <algorithm> #include <iostream> ...

  5. C# 为WebBrowser设置代理,打开网页

    WebBrowser控件是基于IE浏览器的,所以它的内核功能是依赖于IE的,相信做.NET的人都知道. 今天的主题,和上一篇文章应该是差不多的,都是通过代理来实现功能的. 请看下面的代码: //1.定 ...

  6. 用vi修改文件,保存文件时,提示“readonly option is set”的解决方法

    来源:http://superuser.com/questions/300500/ubuntu-unable-to-edit-bashrc-file-because-of-readonly This ...

  7. Linux 查看端口占用并杀掉

    1. 查看端口号占用情况: netstat -apn|grep 80 tcp        0      0 10.65.42.27:80              172.22.142.20:627 ...

  8. UVa 10791 Minimum Sum LCM【唯一分解定理】

    题意:给出n,求至少两个正整数,使得它们的最小公倍数为n,且这些整数的和最小 看的紫书--- 用唯一分解定理,n=(a1)^p1*(a2)^p2---*(ak)^pk,当每一个(ak)^pk作为一个单 ...

  9. HDU 1051 Wooden Sticks【LIS】

    题意:给出n个木头的重量wi,长度li,如果满足w[i+1]>=w[i]且l[i+1]>=l[i],则不用耗费另外的加工时间,问至少需要多长时间加工完这些木头. 第一次做这一题目也没有做出 ...

  10. 淘宝主搜索离线集群完成Hadoop 2

    淘宝搜索离线dump集群(hadoop&hbase)2013进行了几次重大升级,本文中将这些升级的详细过程.升级中所遇到的问题以及这些问题的解决方案分享给大家.至此,淘宝主搜索离线集群完全进入 ...