Hadoop 学习之单表连接

我在学习hadoop, 在看 陆嘉恒编著的hadoop实战,其中有单表连接的程序,我现在整理一下思路。这个问题是课本上的例子。

给出 child-parent 表, 要求输出 grandchild-grandparent 表

样例输入:

child parent

Tom Lucy

Tom Jack

Jone Lucy

Jone Jack

Lucy Mary

Lucy Ben

Jack Alice

Jack Jesee

Terry Alice

Terry Jesee

Philip Terry

Philip Alma

Mark Terry

Mark Alma

样例输出:

grandChildgrandParent

TomAlice

TomJesee

JoneAlice

JoneJesee

TomMary

TomBen

JoneMary

JoneBen

PhilipAlice

PhilipJesee

MarkAlice

MarkJesee

其实这个案例只要想通了里面的关键,还是很简单的。

解题思路: 进行单表连接

从样例输入文件中,我们可以看到  child--parent(child)--parent ,通过这样连接就会找出 grandchild -- grandparent

如:

child    parent

Tom    Lucy

Tom   Jack

Lucy Mary

Lucy Ben

Jack Alice

Jack Jesee

这样我们可以很容易的找到下面的关系:

grandchild     grandparent

Tom                    Mary

Tom                    Ben

Tom                    Alice

Tom                    Jesee

我们可以这样连接:

表一:                        表二:

child    parent           child    parent

Tom     Lucy               Lucy   Mary

Lucy  Ben

Tom    Jack               Jack   Alice

Jack  Jesee

我们可以将表一和表二进行连接,然后去掉 表一的第二列 和表二的第一列, 剩下的就是 结果了。

这里我们可以看到 ,其实表一和表二是一个表,这就是单表连接

这里可以将将这个表设置为左表和右表

Map 阶段:

将读入的数据 分割为child 和 parent  , 为了区分左右表可以在 输出的value 里面加上标记左右表的信息, 左表 将 parent 作为key , 左表标记+child 作为 value    为map输出, 右表 child 作为key ,右表标记+parent 作为value  为输出。

在Map 阶段完成了左右表的划分,在shuffle 阶段完成了左右表连接

Reduce 阶段:

(相同key 的 会汇聚在一起,如  <Lucy ,<leftTag:Tom , rightTag:Mary , rightTag:Ben> >)

像这样在Reduce 阶段收到的结果中,每个key的value-list 中就包含了grandchild (left:Tom)和grandparnet (rightTag : Mary , rgihtTag : Ben)的关系,然后将value解析, 有leftTag标记的存入 grandChild[] 数组中,将有rightTag 标记的 存入 grandParent[] 数组中,然后对 grandChild[] 和grandParent[] 求笛卡尔积 即可

下面是程序代码:

package cn.edu.ytu.botao.singletablejoin;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
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.util.GenericOptionsParser;

/**
 * 
 * 单表连接
 * 
 * child   parent
 * Tom      Lucy
 * Tom      Jack
 * Lucy      Mary
 * Lucy      Ben
 * 
 * 左表 :   反向输出  <key parent, value chlid>
 * Lucy  Tom
 * Jack  Tom
 * 
 * 右表      正向输出  <key child, value parent>
 * Lucy  Mary
 * Lucy  Ben
 * 
 * 连接后:
 * 
 * <Tom, <Mary , Ben> >
 * 
 * @author botao
 *
 */

public class STjoin {
	private static int time = 0;
	public static class STJMapper extends Mapper<Object, Text, Text, Text>{
		//标记表
		private Text leftTag = new Text("1");     //左表
		private Text rightTag = new Text("2");   //右表

		@Override
		protected void map(Object key, Text value,
				Context context)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub

			String childName = new String();
			String parentName = new String();
			//读取内容
			String line = value.toString();
			StringTokenizer tokenizer = new StringTokenizer(line);

			//截取的字符串数组
			String[] values = new String[2];
			int i = 0;
			while (tokenizer.hasMoreElements()) {
				values[i++] = (String) tokenizer.nextElement();
			}

			if (values[0].compareTo("child") != 0) {
				childName = values[0];
				parentName = values[1];

				//左表输出 反向   value的值为 grandchild
				context.write(new Text(parentName), new Text(leftTag.toString() + ":" + childName));
				//右表输出 正向
				context.write(new Text(childName), new Text(rightTag.toString() + ":" + parentName));
			}

		}

	}

	public static class STJoinReduce extends Reducer<Text, Text, Text, Text>{

		@Override
		protected void reduce(Text key, Iterable<Text> values,
				Context context)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub

			//记录grandchild的信息 和存储
			int grandChlidNum = 0;
			String[] grandChild = new String[20];

			//记录grandparent 的信息 和存储
			int grandParentNum = 0;
			String[] grandParent = new String[20];

			if (time == 0) {
				context.write(new Text("grandChild"), new Text("grandParent"));
				time++;
			}

			/**
			 * 对于右表 将values的值存入 grandChild[] 中
			 * 对于左表 将values 的值存入 grandParnet[] 中
			 */
			for (Text text : values) {
				String value = text.toString();
				//System.out.println(key.toString() + "..." + value);
				String temp[] = value.split(":");
				//System.out.println(key.toString() + "....." + temp[0] + "..." + temp[1]);
				//左表
				if (temp[0].compareTo("1") == 0) {

					grandChild[grandChlidNum++] = temp[1];

				}

				if (temp[0].compareTo("2") == 0) {
					grandParent[grandParentNum++] = temp[1];

				}

			}

			//对 grandChild[] 和 grandParent[]进行求笛卡尔积
			if (0 != grandChlidNum && 0 != grandParentNum) {
				//System.out.println(grandChlidNum + "..." + grandParentNum);
				for (int i = 0; i < grandChlidNum; i++) {
					for (int j = 0; j < grandParentNum; j++) {
						context.write(new Text(grandChild[i]), new Text(grandParent[j]));
					}
				}
			}
		}

	}

	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		Configuration conf = new Configuration();
	    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount <in> <out>");
			System.exit(2);
		}

		// 如果out文件夹存在,现将该文件夹删除
		Path path = new Path("out");
		FileSystem fs = FileSystem.get(conf);
		if (fs.exists(path)) {
			fs.delete(path);
		}
	    
	    
	    Job job = new Job(conf , "STJoin");
	    job.setJarByClass(STjoin.class);
	    job.setMapperClass(STJMapper.class);
	    job.setReducerClass(STJoinReduce.class);
	    job.setOutputKeyClass(Text.class);
	    job.setOutputValueClass(Text.class);
	    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
	    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
	    System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
}
时间: 2024-10-31 01:18:14

Hadoop 学习之单表连接的相关文章

Hadoop阅读笔记(三)——深入MapReduce排序和单表连接

继上篇了解了使用MapReduce计算平均数以及去重后,我们再来一探MapReduce在排序以及单表关联上的处理方法.在MapReduce系列的第一篇就有说过,MapReduce不仅是一种分布式的计算方法,更是一种解决问题的新思维.新思路.将原先看似可以一条龙似的处理一刀切成两端,一端是Map.一端是Reduce,Map负责分,Reduce负责合. 1.MapReduce排序 问题模型: 给出多个数据文件输入如: sortfile1.txt 11 13 15 17 19 21 23 25 27

MySQL学习9 - 单表查询

一.单表查询的语法 二.关键字的执行优先级(重点) 三.单表查询示例 1.where约束 2.group by分组查询 3.聚合函数 4.HAVING过滤 5.order by查询排序 6.limit 限制查询的记录数 一.单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二.关键字的执行优先级(重点) 重点中的重点:关键字的执行优先级 from where

MySql数据库再学习——简述多表连接查询的自我理解

一:序 这几天在学习数据库部分,因为在学校听课也是比较迷糊,经过学习之后感觉现在思路比较清楚,对于多表连接查询操作有了一个新的认识. 二:假设 假设现在有两个表 :A ,B. 三:两表之间的连接方式 两个表的连接方式分为,内,外,交叉三种. 内连接的查询方式又分为隐式和显式两种. 外连接的查询方式又分为左,右两种. 交叉是将两个表的记录做乘积,因为得到的记录很大程度上没有直接联系,所以交叉连接查询基本没什么意义. 四:内连接 内连接的关键词:inner join...(inner可以省略) 隐式

mysql 学习 - 掌握单表查询优化

MySQL Server有一个称为查询优化器的模块,一条查询语句进行语法解析之后就会被交给查询优化器来进行优化,优化的结果就是生成一个所谓的执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的,最后会按照执行计划中的步骤调用存储引擎提供的方法来真正的执行查询,并将查询结果返回给用户.但是在介绍查询优化器之前, 我们需要先对单表查询的优化进行一定程度上的掌握. 建表 CREATE TABLE single_table ( id INT NOT NULL AUTO_INCR

SQLServer学习(多表连接查询)(四)

(1)双表内部连接查询 ①在where中指定内部连接的条件(这种写法使用的很少) SELECT WorkNo,Name,DeptName,SignImg FROM S_A_User,S_A_UserImg WHERE S_A_User.ID=S_A_UserImg.UserID ORDER BY DeptName,Name ②在from中指定内部连接的条件(推荐使用) SELECT WorkNo,Name,DeptName,SignImg FROM S_A_User INNER JOIN S_A

Linq学习(五)-多表连接

本将主要介绍 内连接与 外连接 1.join Linq to sql from a in Blog_Users join b in Blog_UserInfo on a.UserId equals b.ID select new { 昵称=a.NickName, 真实名=b.RealName } sql SELECT [t0].[NickName] AS [昵称], [t1].[RealName] AS [真实名] FROM [Blog_User] AS [t0] INNER JOIN [Blo

三、Django学习之单表查询接口

查询接口 all() 查询所有结果,结果是queryset类型 filter(**kwargs) and条件关系:参数用逗号分割表示and关系 models.Student.objects.filter(id=1,name='dazhuang').update( name='大壮禅师', age = 78, ) 其中filter的参数也可以通过字典方式传入 odels.Student.objects.filter(**{'id':7,'name':'大壮禅师'}).update(age=100)

MapReduce程序之实现单表关联

设计思路 分析这个实例,显然需要进行单表连接,连接的是左表的parent列和右表的child列,且左表和右表是同一个表. 连接结果中除去连接的两列就是所需要的结果--"grandchild--grandparent"表.要用MapReduce解决这个实例,首先应该考虑如何实现表的自连接:其次就是连接列的设置:最后是结果的整理. 考虑到MapReduce的shuffle过程会将相同的key会连接在一起,所以可以将map结果的key设置成待连接的列,然后列中相同的值就自然会连接在一起了.再

MapReduce编程系列 — 5:单表关联

1.项目名称: 2.项目数据: chile    parentTom    LucyTom    JackJone    LucyJone    JackLucy    MaryLucy    BenJack    AliceJack    JesseTerry    AliceTerry    JessePhilip    TerryPhilip    AlimaMark    TerryMark    Alma 3.设计思路: 分析这个实例,显然需要进行单表连接,连接的是左表的parent列