MapReduce Join关联
1、Reduce join(合并)
原理
Map端的主要工作:为来自不同表(文件)的key/value对打标签以区别不同来源的记录。然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
Reduce端的主要工作:在reduce端以连接字段作为key的分组已经完成,我们只需要在每一个分组当中将那些来源于不同文件的记录(在map阶段已经打标志)分开,最后进行合并就ok了。
2、Reduce join案例实操
(1)需求
订单数据表t_order
order.txt
1001 01 1
1002 02 2
1003 03 3
1004 01 4
1005 02 5
1006 03 6
商品信息表t_product
pd.txt
01 小米
02 华为
03 格力
sql:select * from t_order o join t_product p on o.pid=p.pid; 笛卡尔积,join条件:t_order.pid=t_product.pid;
将商品信息表中数据根据商品pid合并到订单数据表中。
最终数据形式
通过将关联条件作为map输出的key,将两表满足join条件的数据(包含数据来源于哪一个文件的标识),发往同一个reduce task,在reduce中进行数据的串联,如图所示:
reduce端表合并
(2)代码实现
a)创建商品和订单合并后的bean类
package com.bigdata.reducejoin;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
//1001 01 1
//01 小米
//02 华为
//03 格力
public class OrderBean implements Writable{
//订单id
private int oid;
//商品id
private int pid;
//商品数量
private int amount;
//商品名称
private String pname;
//bean的标记 0:标记该bean来自于order.txt 1:来自于pd.txt
private String flag ;
public OrderBean() {
super();
// TODO Auto-generated constructor stub
}
public OrderBean(int oid, int pid, int amount, String pname, String flag) {
super();
this.oid = oid;
this.pid = pid;
this.amount = amount;
this.pname = pname;
this.flag = flag;
}
public int getOid() {
return oid;
}
public void setOid(int oid) {
this.oid = oid;
}
public int getPid() {
return pid;
}
public void setPid(int 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;
}
public void write(DataOutput out) throws IOException {
out.writeInt(oid);
out.writeInt(pid);
out.writeInt(amount);
//注意:字符串的序列化写法
out.writeUTF(pname);
out.writeUTF(flag);
}
public void readFields(DataInput in) throws IOException {
oid = in.readInt();
pid = in.readInt();