在reduce端实现两表的join
reduce side join是一种最简单的join方式,其主要思想如下:
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。
在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list, 然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。
reduce side join是一种最简单的join方式,其主要思想如下:
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。
在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list, 然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。
主要技巧有:
1、在map端,通过读取文件路径识别具体数据是从哪个文件读取的,然后在value里加上这个文件的标签(tag)。
2、在reduce端,通过分离出map加入的tag,识别出数据属于哪个文件,然后使用vector容器存储每个文件的value,最后用两个for循环遍历即可。
简单代码:
public class join extends Configured implements Tool{
public static class joinmapper extends Mapper<Longwritable, Text, Text, Text>{
protected void map(Longwritable key, Text value, Context context)
throws IOException, InterruptedException{
String filepath = ((FileSplit)context.getInputSplit()).getPath().toString();
String line = value.toString();
if (filepath.indexOf("employee") != -1) {
String[] lines = line.split("\t", 2);
String company_id = lines[0];
String employee = lines[1];
context.write(new Text(company_id), new Text("a:" + employee));
} else if (filepath.indexOf("salary") != -1) {
String[] lines = line.split("\t", 2);
String company_id = lines[0];
String salary = lines[1];
context.write(new Text(company_id), new Text("b:" + salary));
}
}
}
public static class joinreduce extends Reducer<Text, Text, Text, Text> {
protected void reduce(Text key, Iterable<Text> values, Context context)
throws IOException, InterruptedException{
Vector<String> a = new Vector<String>();
Vector<String> b = new Vector<String>();
for (Text value : values) {
String line = value.toString();
String[] lines = line.split(":");
if (lines[0] == "a"){
a.add(lines[1]);
} else if (lines[0] == "b"){
b.add(lines[1]);
}
}
for (int i=0; i<a.size(); i++) {
for (int j=0; j<b.size(); j++) {
context.write(key, new Text(a.get(i) + '\t' + b.get(j)));
}
}
}
}
public int run(String[] args) throws Exception {
Configuration conf = getConf();
Job job = new Job(conf, "join");
job.setJarByClass(join.class);
job.setMapperClass(joinmapper.class);
job.setReducerClass(joinreduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
return job.waitForCompletion(true) ? 0 : 1;
}
public static void main(String[] args) throws Exception{
int res = ToolRunner.run(new Configuration(), new join(), args);
System.exit(res);
}
}