map端join
指有两种表,只是一张较小,一张较大(一般大于1万条数据),大表的信息完全可以覆盖小表,往往将较小的表以键值对的形式添加到内存中,,然后只扫描大表:对于大表中的每一条记录key/value,在小表中查找是否有相同的key的记录,如果有,则连接后输出即可。
Map端join是数据到达map处理函数之前进行合并的,效率要远远高于Reduce端join,因为Reduce端join是把所有的数据都经过Shuffle,非常消耗资源。所以一般都用Map端join。
操作流程
1.以键值对形式存储小表信息;
2.在Mapper.setup(Context context)函数里读取该文件并存到Map中;
3.读大表信息,根据外键关联,大表的第二列就是小表的第一列,所以键相同,然后通过大表的第二列的键获取小表中的值,将得到的值将填充回大表中的第二列;
4.将最后得到的值转为字符串;
5.将结果输出(即没有Reduce任务)。
上代码:
public class MyMapJoin {
public static class MyMapper extends Mapper<LongWritable, Text,Text, NullWritable>{
private Map myType = new HashMap();//存储小表信息
@Override
protected void setup(Context context) throws IOException, InterruptedException {
//获取缓存中的小表,返回的是小表的URI
String fileName = context.getCacheFiles()[0].getPath();
final BufferedReader read = new BufferedReader(new FileReader(fileName));//buffer读数据增加效率
String str = null;
while ((str=read.readLine())!=null){
String [] sps = str.split(",");//通过逗号进行分割
myType.put(sps[0],sps[1]);//分割后第一列放到键,第二列放到值
}
read.close();
}
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException
//读大表
String [] goodInfos = value.toString().split(",");
//根据主外键获取大表分类,外键就是第2列,根据外键获取小表第一列的值
String type = myType.