Map Join和Reduce Join
俩种Join的介绍
MapReduce Join
对两份数据data1和data2进行关键词连接是一个很通用的问题。
如果数据量比较小,完全可以在内存中完成连接;如果数据量比较大,在内存进行连接操会发生内存溢出(OOM)。那么此时就可以用 MapReduce Join 来解决大数据的连接问题。
Reduce Join
map 端的主要工作:为来自不同表(文件)的key/value 打标记以区别不同来源的记录。然后用连接字段作为 key,其余部分和新加的标记作为 value,然后进行输出。
reduce 端的主要工作:在 reduce 端,以连接字段作为key 的分组已经完成,我们只需要在每一个分组当中将那些来源于不同文件的记录(在 map 阶段已经打标记)分开,最后进行合并就 ok 了。
通俗的说,就是在map 阶段, 把关键字作为key输出,并在value中标记出数据是来自data1还是data2。因为在shuffle阶段已经自然按key分组,reduce 阶段,判断每一个value是来自data1还是data2,在内部分成2组,做集合的乘积。
- 但是,此方法有缺点:
1、map 阶段没有对数据瘦身,shuffle的网络传输和排序性能很低。
2、reduce 端对2个集合做乘积计算,很耗内存,容易导致OOM。
Map Join
两份数据中,如果有一份数据比较小,小数据全部加载到内存,按关键字建立索引。大数据文件作为map的输入文件,对map()方法的每一对输入,都能够方便地和已加载到内存的小数据进行连接。把连接结果按key输出,经过shuffle阶段,reduce端得到的就是已经按key分组的,并且连接好了的数据。
此方法的特点:
1、要使用hadoop中的DistributedCache(分布式缓存)把小数据分布到各个计算节点,每个map节点都要把小数据库加载到内存,按关键字建立索引。
2、有明显的局限性:数据中有一份数据比较小,在map端,能够把它加载到内存,并进行join操作。
3、Map Join没有Reduce环节
数据
orders表
products表
将两表以红框选择的字符段进行拼接
Reduce Join
自定义类
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class ReduceJoinBean implements Writable {
private String id;
private String date;
private String pid;
private String amount;
private String pname;
private String category_id;
private String price;
private String fileName;
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(id);
out.writeUTF(date);
out.writeUTF(pid);
out.writeUTF(amount);
out.writeUTF(pname);
out.writeUTF(category_id);
out.writeUTF(price);
out.writeUTF(fileName);
}
@Override
public void readFields(DataInput in) throws IOException {
this.id = in.readUTF();
this.date = in.readUTF();
this.pid = in.readUTF();
this.amount = in.readUTF();
this.pname = in.readUTF();
this.category_id = in.readUTF();
this.price = in.readUTF();
this.fileName = in.readUTF();
}
public void set(String id, String date, String pid, String amount, String pname, String category_id, String price, String fileName) {
this.id = id;
this.date = date;
this.pid = pid;
this.amount = amount;
this.pname = pname;
this.category_id = category_id;
this.price = price;
this.fileName = fileName;
}
@Override
public String toString() {
return id + '\t' +
date + '\t' +
pid + '\t' +
amount + '\t' +
pname + '\t' +
category_id + '\t' +
price + '\t';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getPid() {