写了关于Hadoop下载地址的Map侧join 
和Reduce的join,今天我们就来在看另外一种比较中立的Join。

SemiJoin,一般称为半链接,其原理是在Map侧过滤掉了一些不需要join的数据,从而大大减少了reduce的shffule时间,因为我们知道,如果仅仅使用Reduce侧连接,那么如果一份数据中,存在大量的无效数据,而这些数据,在join中,并不需要,但是因为没有做过预处理,所以这些数据,直到真正的执行reduce函数时,才被定义为无效数据,而这时候,前面已经执行过shuffle和merge和sort,所以这部分无效的数据,就浪费了大量的网络IO和磁盘IO,所以在整体来讲,这是一种降低性能的表现,如果存在的无效数据越多,那么这种趋势,就越明显。

之所以会出现半连接,这其实也是reduce侧连接的一个变种,只不过我们在Map侧,过滤掉了一些无效的数据,所以减少了reduce过程的shuffle时间,所以能获取一个性能的提升。

具体的原理也是利用DistributedCache将小表的的分发到各个节点上,在Map过程的setup函数里,读取缓存里面的文件,只将小表的链接键存储在hashset里,在map函数执行时,对每一条数据,进行判断,如果这条数据的链接键为空或者在hashset里面不存在,那么则认为这条数据,是无效的数据,所以这条数据,并不会被partition分区后写入磁盘,参与reduce阶段的shuffle和sort下载地址  ,所以在一定程序上,提升了join性能。需要注意的是如果 
小表的key依然非常巨大,可能会导致我们的程序出现OOM的情况,那么这时候我们就需要考虑其他的链接方式了。

测试数据如下: 
模拟小表数据: 
1,三劫散仙,13575468248 
2,凤舞九天,18965235874 
3,忙忙碌碌,15986854789 
4,少林寺方丈,15698745862

模拟大表数据: 
3,A,99,2013-03-05 
1,B,89,2013-02-05 
2,C,69,2013-03-09 
3,D,56,2013-06-07 
5,E,100,2013-09-09 
6,H,200,2014-01-10

代码如下:

  1. package com.semijoin;
  2. import java.io.BufferedReader;
  3. import java.io.DataInput;
  4. import java.io.DataOutput;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. import java.net.URI;
  8. import java.util.ArrayList;
  9. import java.util.HashSet;
  10. import java.util.List;
  11. import org.apache.hadoop.conf.Configuration;
  12. import org.apache.hadoop.filecache.DistributedCache;
  13. import org.apache.hadoop.fs.FileSystem;
  14. import org.apache.hadoop.fs.Path;
  15. import org.apache.hadoop.io.LongWritable;
  16. import org.apache.hadoop.io.Text;
  17. import org.apache.hadoop.io.WritableComparable;
  18. import org.apache.hadoop.mapred.JobConf;
  19. import org.apache.hadoop.mapreduce.Job;
  20. import org.apache.hadoop.mapreduce.Mapper;
  21. import org.apache.hadoop.mapreduce.Reducer;
  22. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  23. import org.apache.hadoop.mapreduce.lib.input.FileSplit;
  24. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
  25. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  26. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
  27. /***
  28. *
  29. * Hadoop1.2的版本
  30. *
  31. * hadoop的半链接
  32. *
  33. * SemiJoin实现
  34. *
  35. * @author qindongliang
  36. *
  37. *    大数据交流群:376932160
  38. *  搜索技术交流群:324714439
  39. *
  40. *
  41. *
  42. * **/
  43. public class Semjoin {
  44. /**
  45. *
  46. *
  47. * 自定义一个输出实体
  48. *
  49. * **/
  50. private static class CombineEntity implements WritableComparable<CombineEntity>{
  51. private Text joinKey;//连接key
  52. private Text flag;//文件来源标志
  53. private Text secondPart;//除了键外的其他部分的数据
  54. public CombineEntity() {
  55. // TODO Auto-generated constructor stub
  56. this.joinKey=new Text();
  57. this.flag=new Text();
  58. this.secondPart=new Text();
  59. }
  60. public Text getJoinKey() {
  61. return joinKey;
  62. }
  63. public void setJoinKey(Text joinKey) {
  64. this.joinKey = joinKey;
  65. }
  66. public Text getFlag() {
  67. return flag;
  68. }
  69. public void setFlag(Text flag) {
  70. this.flag = flag;
  71. }
  72. public Text getSecondPart() {
  73. return secondPart;
  74. }
  75. public void setSecondPart(Text secondPart) {
  76. this.secondPart = secondPart;
  77. }
  78. @Override
  79. public void readFields(DataInput in) throws IOException {
  80. this.joinKey.readFields(in);
  81. this.flag.readFields(in);
  82. this.secondPart.readFields(in);
  83. }
  84. @Override
  85. public void write(DataOutput out) throws IOException {
  86. this.joinKey.write(out);
  87. this.flag.write(out);
  88. this.secondPart.write(out);
  89. }
  90. @Override
  91. public int compareTo(CombineEntity o) {
  92. // TODO Auto-generated method stub
  93. return this.joinKey.compareTo(o.joinKey);
  94. }
  95. }
  96. private static class JMapper extends Mapper<LongWritable, Text, Text, CombineEntity>{
  97. private CombineEntity combine=new CombineEntity();
  98. private Text flag=new Text();
  99. private  Text joinKey=new Text();
  100. private Text secondPart=new Text();
  101. /**
  102. * 存储小表的key
  103. *
  104. *
  105. * */
  106. private HashSet<String> joinKeySet=new HashSet<String>();
  107. @Override
  108. protected void setup(Context context)throws IOException, InterruptedException {
  109. //读取文件流
  110. BufferedReader br=null;
  111. String temp;
  112. // 获取DistributedCached里面 的共享文件
  113. Path path[]=DistributedCache.getLocalCacheFiles(context.getConfiguration());
  114. for(Path p:path){
  115. if(p.getName().endsWith("a.txt")){
  116. br=new BufferedReader(new FileReader(p.toString()));
  117. //List<String> list=Files.readAllLines(Paths.get(p.getName()), Charset.forName("UTF-8"));
  118. while((temp=br.readLine())!=null){
  119. String ss[]=temp.split(",");
  120. //map.put(ss[0], ss[1]+"\t"+ss[2]);//放入hash表中
  121. joinKeySet.add(ss[0]);//加入小表的key
  122. }
  123. }
  124. }
  125. }
  126. @Override
  127. protected void map(LongWritable key, Text value,Context context)
  128. throws IOException, InterruptedException {
  129. //获得文件输入路径
  130. String pathName = ((FileSplit) context.getInputSplit()).getPath().toString();
  131. if(pathName.endsWith("a.txt")){
  132. String  valueItems[]=value.toString().split(",");
  133. /**
  134. * 在这里过滤必须要的连接字符
  135. *
  136. * */
  137. if(joinKeySet.contains(valueItems[0])){
  138. //设置标志位
  139. flag.set("0");
  140. //设置链接键
  141. joinKey.set(valueItems[0]);
  142. //设置第二部分
  143. secondPart.set(valueItems[1]+"\t"+valueItems[2]);
  144. //封装实体
  145. combine.setFlag(flag);//标志位
  146. combine.setJoinKey(joinKey);//链接键
  147. combine.setSecondPart(secondPart);//其他部分
  148. //写出
  149. context.write(combine.getJoinKey(), combine);
  150. }else{
  151. System.out.println("a.txt里");
  152. System.out.println("在小表中无此记录,执行过滤掉!");
  153. for(String v:valueItems){
  154. System.out.print(v+"   ");
  155. }
  156. return ;
  157. }
  158. }else if(pathName.endsWith("b.txt")){
  159. String  valueItems[]=value.toString().split(",");
  160. /**
  161. *
  162. * 判断是否在集合中
  163. *
  164. * */
  165. if(joinKeySet.contains(valueItems[0])){
  166. //设置标志位
  167. flag.set("1");
  168. //设置链接键
  169. joinKey.set(valueItems[0]);
  170. //设置第二部分注意不同的文件的列数不一样
  171. secondPart.set(valueItems[1]+"\t"+valueItems[2]+"\t"+valueItems[3]);
  172. //封装实体
  173. combine.setFlag(flag);//标志位
  174. combine.setJoinKey(joinKey);//链接键
  175. combine.setSecondPart(secondPart);//其他部分
  176. //写出
  177. context.write(combine.getJoinKey(), combine);
  178. }else{
  179. //执行过滤 ......
  180. System.out.println("b.txt里");
  181. System.out.println("在小表中无此记录,执行过滤掉!");
  182. for(String v:valueItems){
  183. System.out.print(v+"   ");
  184. }
  185. return ;
  186. }
  187. }
  188. }
  189. }
  190. private static class JReduce extends Reducer<Text, CombineEntity, Text, Text>{
  191. //存储一个分组中左表信息
  192. private List<Text> leftTable=new ArrayList<Text>();
  193. //存储一个分组中右表信息
  194. private List<Text> rightTable=new ArrayList<Text>();
  195. private Text secondPart=null;
  196. private Text output=new Text();
  197. //一个分组调用一次
  198. @Override
  199. protected void reduce(Text key, Iterable<CombineEntity> values,Context context)
  200. throws IOException, InterruptedException {
  201. leftTable.clear();//清空分组数据
  202. rightTable.clear();//清空分组数据
  203. /**
  204. * 将不同文件的数据,分别放在不同的集合
  205. * 中,注意数据量过大时,会出现
  206. * OOM的异常
  207. *
  208. * **/
  209. for(CombineEntity ce:values){
  210. this.secondPart=new Text(ce.getSecondPart().toString());
  211. //左表
  212. if(ce.getFlag().toString().trim().equals("0")){
  213. leftTable.add(secondPart);
  214. }else if(ce.getFlag().toString().trim().equals("1")){
  215. rightTable.add(secondPart);
  216. }
  217. }
  218. //=====================
  219. for(Text left:leftTable){
  220. for(Text right:rightTable){
  221. output.set(left+"\t"+right);//连接左右数据
  222. context.write(key, output);//输出
  223. }
  224. }
  225. }
  226. }
  227. public static void main(String[] args)throws Exception {
  228. //Job job=new Job(conf,"myjoin");
  229. JobConf conf=new JobConf(Semjoin.class);
  230. conf.set("mapred.job.tracker","192.168.75.130:9001");
  231. conf.setJar("tt.jar");
  232. //小表共享
  233. String bpath="hdfs://192.168.75.130:9000/root/dist/a.txt";
  234. //添加到共享cache里
  235. DistributedCache.addCacheFile(new URI(bpath), conf);
  236. Job job=new Job(conf, "aaaaa");
  237. job.setJarByClass(Semjoin.class);
  238. System.out.println("模式:  "+conf.get("mapred.job.tracker"));;
  239. //设置Map和Reduce自定义类
  240. job.setMapperClass(JMapper.class);
  241. job.setReducerClass(JReduce.class);
  242. //设置Map端输出
  243. job.setMapOutputKeyClass(Text.class);
  244. job.setMapOutputValueClass(CombineEntity.class);
  245. //设置Reduce端的输出
  246. job.setOutputKeyClass(Text.class);
  247. job.setOutputValueClass(Text.class);
  248. job.setInputFormatClass(TextInputFormat.class);
  249. job.setOutputFormatClass(TextOutputFormat.class);
  250. FileSystem fs=FileSystem.get(conf);
  251. Path op=new Path("hdfs://192.168.75.130:9000/root/outputjoindbnew4");
  252. if(fs.exists(op)){
  253. fs.delete(op, true);
  254. System.out.println("存在此输出路径,已删除!!!");
  255. }
  256. FileInputFormat.setInputPaths(job, new Path("hdfs://192.168.75.130:9000/root/inputjoindb"));
  257. FileOutputFormat.setOutputPath(job, op);
  258. System.exit(job.waitForCompletion(true)?0:1);
  259. }
  260. }
  1. package com.semijoin;
  2. import java.io.BufferedReader;
  3. import java.io.DataInput;
  4. import java.io.DataOutput;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. import java.net.URI;
  8. import java.util.ArrayList;
  9. import java.util.HashSet;
  10. import java.util.List;
  11. import org.apache.hadoop.conf.Configuration;
  12. import org.apache.hadoop.filecache.DistributedCache;
  13. import org.apache.hadoop.fs.FileSystem;
  14. import org.apache.hadoop.fs.Path;
  15. import org.apache.hadoop.io.LongWritable;
  16. import org.apache.hadoop.io.Text;
  17. import org.apache.hadoop.io.WritableComparable;
  18. import org.apache.hadoop.mapred.JobConf;
  19. import org.apache.hadoop.mapreduce.Job;
  20. import org.apache.hadoop.mapreduce.Mapper;
  21. import org.apache.hadoop.mapreduce.Reducer;
  22. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  23. import org.apache.hadoop.mapreduce.lib.input.FileSplit;
  24. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
  25. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  26. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
  27. /***
  28. *
  29. * Hadoop1.2的版本
  30. *
  31. * hadoop的半链接
  32. *
  33. * SemiJoin实现
  34. *
  35. * @author qindongliang
  36. *
  37. *    大数据交流群:376932160
  38. *  搜索技术交流群:324714439
  39. *
  40. *
  41. *
  42. * **/
  43. public class Semjoin {
  44. /**
  45. *
  46. *
  47. * 自定义一个输出实体
  48. *
  49. * **/
  50. private static class CombineEntity implements WritableComparable<CombineEntity>{
  51. private Text joinKey;//连接key
  52. private Text flag;//文件来源标志
  53. private Text secondPart;//除了键外的其他部分的数据
  54. public CombineEntity() {
  55. // TODO Auto-generated constructor stub
  56. this.joinKey=new Text();
  57. this.flag=new Text();
  58. this.secondPart=new Text();
  59. }
  60. public Text getJoinKey() {
  61. return joinKey;
  62. }
  63. public void setJoinKey(Text joinKey) {
  64. this.joinKey = joinKey;
  65. }
  66. public Text getFlag() {
  67. return flag;
  68. }
  69. public void setFlag(Text flag) {
  70. this.flag = flag;
  71. }
  72. public Text getSecondPart() {
  73. return secondPart;
  74. }
  75. public void setSecondPart(Text secondPart) {
  76. this.secondPart = secondPart;
  77. }
  78. @Override
  79. public void readFields(DataInput in) throws IOException {
  80. this.joinKey.readFields(in);
  81. this.flag.readFields(in);
  82. this.secondPart.readFields(in);
  83. }
  84. @Override
  85. public void write(DataOutput out) throws IOException {
  86. this.joinKey.write(out);
  87. this.flag.write(out);
  88. this.secondPart.write(out);
  89. }
  90. @Override
  91. public int compareTo(CombineEntity o) {
  92. // TODO Auto-generated method stub
  93. return this.joinKey.compareTo(o.joinKey);
  94. }
  95. }
  96. private static class JMapper extends Mapper<LongWritable, Text, Text, CombineEntity>{
  97. private CombineEntity combine=new CombineEntity();
  98. private Text flag=new Text();
  99. private  Text joinKey=new Text();
  100. private Text secondPart=new Text();
  101. /**
  102. * 存储小表的key
  103. *
  104. *
  105. * */
  106. private HashSet<String> joinKeySet=new HashSet<String>();
  107. @Override
  108. protected void setup(Context context)throws IOException, InterruptedException {
  109. //读取文件流
  110. BufferedReader br=null;
  111. String temp;
  112. // 获取DistributedCached里面 的共享文件
  113. Path path[]=DistributedCache.getLocalCacheFiles(context.getConfiguration());
  114. for(Path p:path){
  115. if(p.getName().endsWith("a.txt")){
  116. br=new BufferedReader(new FileReader(p.toString()));
  117. //List<String> list=Files.readAllLines(Paths.get(p.getName()), Charset.forName("UTF-8"));
  118. while((temp=br.readLine())!=null){
  119. String ss[]=temp.split(",");
  120. //map.put(ss[0], ss[1]+"\t"+ss[2]);//放入hash表中
  121. joinKeySet.add(ss[0]);//加入小表的key
  122. }
  123. }
  124. }
  125. }
  126. @Override
  127. protected void map(LongWritable key, Text value,Context context)
  128. throws IOException, InterruptedException {
  129. //获得文件输入路径
  130. String pathName = ((FileSplit) context.getInputSplit()).getPath().toString();
  131. if(pathName.endsWith("a.txt")){
  132. String  valueItems[]=value.toString().split(",");
  133. /**
  134. * 在这里过滤必须要的连接字符
  135. *
  136. * */
  137. if(joinKeySet.contains(valueItems[0])){
  138. //设置标志位
  139. flag.set("0");
  140. //设置链接键
  141. joinKey.set(valueItems[0]);
  142. //设置第二部分
  143. secondPart.set(valueItems[1]+"\t"+valueItems[2]);
  144. //封装实体
  145. combine.setFlag(flag);//标志位
  146. combine.setJoinKey(joinKey);//链接键
  147. combine.setSecondPart(secondPart);//其他部分
  148. //写出
  149. context.write(combine.getJoinKey(), combine);
  150. }else{
  151. System.out.println("a.txt里");
  152. System.out.println("在小表中无此记录,执行过滤掉!");
  153. for(String v:valueItems){
  154. System.out.print(v+"   ");
  155. }
  156. return ;
  157. }
  158. }else if(pathName.endsWith("b.txt")){
  159. String  valueItems[]=value.toString().split(",");
  160. /**
  161. *
  162. * 判断是否在集合中
  163. *
  164. * */
  165. if(joinKeySet.contains(valueItems[0])){
  166. //设置标志位
  167. flag.set("1");
  168. //设置链接键
  169. joinKey.set(valueItems[0]);
  170. //设置第二部分注意不同的文件的列数不一样
  171. secondPart.set(valueItems[1]+"\t"+valueItems[2]+"\t"+valueItems[3]);
  172. //封装实体
  173. combine.setFlag(flag);//标志位
  174. combine.setJoinKey(joinKey);//链接键
  175. combine.setSecondPart(secondPart);//其他部分
  176. //写出
  177. context.write(combine.getJoinKey(), combine);
  178. }else{
  179. //执行过滤 ......
  180. System.out.println("b.txt里");
  181. System.out.println("在小表中无此记录,执行过滤掉!");
  182. for(String v:valueItems){
  183. System.out.print(v+"   ");
  184. }
  185. return ;
  186. }
  187. }
  188. }
  189. }
  190. private static class JReduce extends Reducer<Text, CombineEntity, Text, Text>{
  191. //存储一个分组中左表信息
  192. private List<Text> leftTable=new ArrayList<Text>();
  193. //存储一个分组中右表信息
  194. private List<Text> rightTable=new ArrayList<Text>();
  195. private Text secondPart=null;
  196. private Text output=new Text();
  197. //一个分组调用一次
  198. @Override
  199. protected void reduce(Text key, Iterable<CombineEntity> values,Context context)
  200. throws IOException, InterruptedException {
  201. leftTable.clear();//清空分组数据
  202. rightTable.clear();//清空分组数据
  203. /**
  204. * 将不同文件的数据,分别放在不同的集合
  205. * 中,注意数据量过大时,会出现
  206. * OOM的异常
  207. *
  208. * **/
  209. for(CombineEntity ce:values){
  210. this.secondPart=new Text(ce.getSecondPart().toString());
  211. //左表
  212. if(ce.getFlag().toString().trim().equals("0")){
  213. leftTable.add(secondPart);
  214. }else if(ce.getFlag().toString().trim().equals("1")){
  215. rightTable.add(secondPart);
  216. }
  217. }
  218. //=====================
  219. for(Text left:leftTable){
  220. for(Text right:rightTable){
  221. output.set(left+"\t"+right);//连接左右数据
  222. context.write(key, output);//输出
  223. }
  224. }
  225. }
  226. }
  227. public static void main(String[] args)throws Exception {
  228. //Job job=new Job(conf,"myjoin");
  229. JobConf conf=new JobConf(Semjoin.class);
  230. conf.set("mapred.job.tracker","192.168.75.130:9001");
  231. conf.setJar("tt.jar");
  232. //小表共享
  233. String bpath="hdfs://192.168.75.130:9000/root/dist/a.txt";
  234. //添加到共享cache里
  235. DistributedCache.addCacheFile(new URI(bpath), conf);
  236. Job job=new Job(conf, "aaaaa");
  237. job.setJarByClass(Semjoin.class);
  238. System.out.println("模式:  "+conf.get("mapred.job.tracker"));;
  239. //设置Map和Reduce自定义类
  240. job.setMapperClass(JMapper.class);
  241. job.setReducerClass(JReduce.class);
  242. //设置Map端输出
  243. job.setMapOutputKeyClass(Text.class);
  244. job.setMapOutputValueClass(CombineEntity.class);
  245. //设置Reduce端的输出
  246. job.setOutputKeyClass(Text.class);
  247. job.setOutputValueClass(Text.class);
  248. job.setInputFormatClass(TextInputFormat.class);
  249. job.setOutputFormatClass(TextOutputFormat.class);
  250. FileSystem fs=FileSystem.get(conf);
  251. Path op=new Path("hdfs://192.168.75.130:9000/root/outputjoindbnew4");
  252. if(fs.exists(op)){
  253. fs.delete(op, true);
  254. System.out.println("存在此输出路径,已删除!!!");
  255. }
  256. FileInputFormat.setInputPaths(job, new Path("hdfs://192.168.75.130:9000/root/inputjoindb"));
  257. FileOutputFormat.setOutputPath(job, op);
  258. System.exit(job.waitForCompletion(true)?0:1);
  259. }
  260. }

运行日志如下:

  1. 模式:  192.168.75.130:9001
  2. 存在此输出路径,已删除!!!
  3. WARN - JobClient.copyAndConfigureFiles(746) | Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
  4. INFO - FileInputFormat.listStatus(237) | Total input paths to process : 2
  5. WARN - NativeCodeLoader.<clinit>(52) | Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
  6. WARN - LoadSnappy.<clinit>(46) | Snappy native library not loaded
  7. INFO - JobClient.monitorAndPrintJob(1380) | Running job: job_201404260312_0002
  8. INFO - JobClient.monitorAndPrintJob(1393) |  map 0% reduce 0%
  9. INFO - JobClient.monitorAndPrintJob(1393) |  map 50% reduce 0%
  10. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 0%
  11. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 33%
  12. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 100%
  13. INFO - JobClient.monitorAndPrintJob(1448) | Job complete: job_201404260312_0002
  14. INFO - Counters.log(585) | Counters: 29
  15. INFO - Counters.log(587) |   Job Counters
  16. INFO - Counters.log(589) |     Launched reduce tasks=1
  17. INFO - Counters.log(589) |     SLOTS_MILLIS_MAPS=12445
  18. INFO - Counters.log(589) |     Total time spent by all reduces waiting after reserving slots (ms)=0
  19. INFO - Counters.log(589) |     Total time spent by all maps waiting after reserving slots (ms)=0
  20. INFO - Counters.log(589) |     Launched map tasks=2
  21. INFO - Counters.log(589) |     Data-local map tasks=2
  22. INFO - Counters.log(589) |     SLOTS_MILLIS_REDUCES=9801
  23. INFO - Counters.log(587) |   File Output Format Counters
  24. INFO - Counters.log(589) |     Bytes Written=172
  25. INFO - Counters.log(587) |   FileSystemCounters
  26. INFO - Counters.log(589) |     FILE_BYTES_READ=237
  27. INFO - Counters.log(589) |     HDFS_BYTES_READ=455
  28. INFO - Counters.log(589) |     FILE_BYTES_WRITTEN=169503
  29. INFO - Counters.log(589) |     HDFS_BYTES_WRITTEN=172
  30. INFO - Counters.log(587) |   File Input Format Counters
  31. INFO - Counters.log(589) |     Bytes Read=227
  32. INFO - Counters.log(587) |   Map-Reduce Framework
  33. INFO - Counters.log(589) |     Map output materialized bytes=243
  34. INFO - Counters.log(589) |     Map input records=10
  35. INFO - Counters.log(589) |     Reduce shuffle bytes=243
  36. INFO - Counters.log(589) |     Spilled Records=16
  37. INFO - Counters.log(589) |     Map output bytes=215
  38. INFO - Counters.log(589) |     Total committed heap usage (bytes)=336338944
  39. INFO - Counters.log(589) |     CPU time spent (ms)=1770
  40. INFO - Counters.log(589) |     Combine input records=0
  41. INFO - Counters.log(589) |     SPLIT_RAW_BYTES=228
  42. INFO - Counters.log(589) |     Reduce input records=8
  43. INFO - Counters.log(589) |     Reduce input groups=4
  44. INFO - Counters.log(589) |     Combine output records=0
  45. INFO - Counters.log(589) |     Physical memory (bytes) snapshot=442564608
  46. INFO - Counters.log(589) |     Reduce output records=4
  47. INFO - Counters.log(589) |     Virtual memory (bytes) snapshot=2184306688
  48. INFO - Counters.log(589) |     Map output records=8
  1. 模式:  192.168.75.130:9001
  2. 存在此输出路径,已删除!!!
  3. WARN - JobClient.copyAndConfigureFiles(746) | Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
  4. INFO - FileInputFormat.listStatus(237) | Total input paths to process : 2
  5. WARN - NativeCodeLoader.<clinit>(52) | Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
  6. WARN - LoadSnappy.<clinit>(46) | Snappy native library not loaded
  7. INFO - JobClient.monitorAndPrintJob(1380) | Running job: job_201404260312_0002
  8. INFO - JobClient.monitorAndPrintJob(1393) |  map 0% reduce 0%
  9. INFO - JobClient.monitorAndPrintJob(1393) |  map 50% reduce 0%
  10. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 0%
  11. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 33%
  12. INFO - JobClient.monitorAndPrintJob(1393) |  map 100% reduce 100%
  13. INFO - JobClient.monitorAndPrintJob(1448) | Job complete: job_201404260312_0002
  14. INFO - Counters.log(585) | Counters: 29
  15. INFO - Counters.log(587) |   Job Counters
  16. INFO - Counters.log(589) |     Launched reduce tasks=1
  17. INFO - Counters.log(589) |     SLOTS_MILLIS_MAPS=12445
  18. INFO - Counters.log(589) |     Total time spent by all reduces waiting after reserving slots (ms)=0
  19. INFO - Counters.log(589) |     Total time spent by all maps waiting after reserving slots (ms)=0
  20. INFO - Counters.log(589) |     Launched map tasks=2
  21. INFO - Counters.log(589) |     Data-local map tasks=2
  22. INFO - Counters.log(589) |     SLOTS_MILLIS_REDUCES=9801
  23. INFO - Counters.log(587) |   File Output Format Counters
  24. INFO - Counters.log(589) |     Bytes Written=172
  25. INFO - Counters.log(587) |   FileSystemCounters
  26. INFO - Counters.log(589) |     FILE_BYTES_READ=237
  27. INFO - Counters.log(589) |     HDFS_BYTES_READ=455
  28. INFO - Counters.log(589) |     FILE_BYTES_WRITTEN=169503
  29. INFO - Counters.log(589) |     HDFS_BYTES_WRITTEN=172
  30. INFO - Counters.log(587) |   File Input Format Counters
  31. INFO - Counters.log(589) |     Bytes Read=227
  32. INFO - Counters.log(587) |   Map-Reduce Framework
  33. INFO - Counters.log(589) |     Map output materialized bytes=243
  34. INFO - Counters.log(589) |     Map input records=10
  35. INFO - Counters.log(589) |     Reduce shuffle bytes=243
  36. INFO - Counters.log(589) |     Spilled Records=16
  37. INFO - Counters.log(589) |     Map output bytes=215
  38. INFO - Counters.log(589) |     Total committed heap usage (bytes)=336338944
  39. INFO - Counters.log(589) |     CPU time spent (ms)=1770
  40. INFO - Counters.log(589) |     Combine input records=0
  41. INFO - Counters.log(589) |     SPLIT_RAW_BYTES=228
  42. INFO - Counters.log(589) |     Reduce input records=8
  43. INFO - Counters.log(589) |     Reduce input groups=4
  44. INFO - Counters.log(589) |     Combine output records=0
  45. INFO - Counters.log(589) |     Physical memory (bytes) snapshot=442564608
  46. INFO - Counters.log(589) |     Reduce output records=4
  47. INFO - Counters.log(589) |     Virtual memory (bytes) snapshot=2184306688
  48. INFO - Counters.log(589) |     Map output records=8

在map侧过滤的数据,在50030中查看的截图如下:

运行结果如下所示:

  1. 1   三劫散仙    13575468248 B   89  2013-02-05
  2. 2   凤舞九天    18965235874 C   69  2013-03-09
  3. 3   忙忙碌碌    15986854789 A   99  2013-03-05
  4. 3   忙忙碌碌    15986854789 D   56  2013-06-07
  1. 1   三劫散仙    13575468248 B   89  2013-02-05
  2. 2   凤舞九天    18965235874 C   69  2013-03-09
  3. 3   忙忙碌碌    15986854789 A   99  2013-03-05
  4. 3   忙忙碌碌    15986854789 D   56  2013-06-07

至此,这个半链接就完成了,结果正确,在hadoop的几种join方式里,只有在Map侧的链接比较高效,但也需要根据具体的实际情况,进行选择。

Hadoop的Map侧join的更多相关文章

  1. hadoop 多表join:Map side join及Reduce side join范例

    最近在准备抽取数据的工作.有一个id集合200多M,要从另一个500GB的数据集合中抽取出所有id集合中包含的数据集.id数据集合中每一个行就是一个id的字符串(Reduce side join要在每 ...

  2. hadoop的压缩解压缩,reduce端join,map端join

    hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...

  3. hadoop中MapReduce多种join实现实例分析

    转载自:http://zengzhaozheng.blog.51cto.com/8219051/1392961 1.在Reudce端进行连接. 在Reudce端进行连接是MapReduce框架进行表之 ...

  4. Hadoop中两表JOIN的处理方法(转)

    1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的.而在HADOOP中进行JOIN操作,同样常见且耗时,由于Hadoop的独特设计思想,当进行JOIN操作时,有一些特殊的 ...

  5. Hadoop中两表JOIN的处理方法

    Dong的这篇博客我觉得把原理写的很详细,同时介绍了一些优化办法,利用二次排序或者布隆过滤器,但在之前实践中我并没有在join中用二者来优化,因为我不是作join优化的,而是做单纯的倾斜处理,做joi ...

  6. Hadoop基础-MapReduce的Join操作

    Hadoop基础-MapReduce的Join操作 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.连接操作Map端Join(适合处理小表+大表的情况) no001 no002 ...

  7. map侧连接

    两个数据集中一个非常小,可以让小数据集存入缓存.在作业开始这些文件会被复制到运行task的节点上. 一开始,它的setup方法会检索缓存文件. 与reduce侧连接不同,Map侧连接需要等待参与连接的 ...

  8. Hadoop_22_MapReduce map端join实现方式解决数据倾斜(DistributedCache)

    1.Map端Join解决数据倾斜   1.Mapreduce中会将map输出的kv对,按照相同key分组(调用getPartition),然后分发给不同的reducetask 2.Map输出结果的时候 ...

  9. 【Spark调优】:如果实在要shuffle,使用map侧预聚合的算子

    因业务上的需要,无可避免的一些运算一定要使用shuffle操作,无法用map类的算子来替代,那么尽量使用可以map侧预聚合的算子. map侧预聚合,是指在每个节点本地对相同的key进行一次聚合操作,类 ...

随机推荐

  1. 延迟渲染 deferred Shading

    流程: 1.先渲染一遍物体的位置,法线  和颜色  到三张纹理 2.在根据这三张纹理渲染一遍灯光 3.合成颜色图和灯光图  (ssao图) 看上去好像灯光不多,其实我在这里加了200个灯, 每个球代表 ...

  2. java中的==和equals

    1,==用于比较基本数据类型,和引用类型.而equals是Object上的方法,可以被子类重写,用于判断内容一致. 比较奇葩的是,java基本数据类型(byte,short,int,long,floa ...

  3. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  4. CRUD Operations In ASP.NET MVC 5 Using ADO.NET

    Background After awesome response of an published by me in the year 2013: Insert, Update, Delete In ...

  5. Codeforces Round #195 A B C 三题合集 (Div. 2)

    A 题 Vasily the Bear and Triangle 题目大意 一个等腰直角三角形 ABC,角 ACB 是直角,AC=BC,点 C 在原点,让确定 A 和 B 的坐标,使得三角形包含一个矩 ...

  6. 电商大促准备流程v2

    1 概述 对于电商企业而言,每年都会有几次大的促销活动,像双十一.店庆等,对于第一次参加这个活动的新手,难免会有些没有头绪,因而将自己参加双十一.双十二活动中的过程心得进行下总结,一方面供以后工作中继 ...

  7. spring 启动流程

    AbstractApplicationContext 分析 启动流程 // Prepare this context for refreshing.prepareRefresh(); 1. // In ...

  8. jquery.uploadify 异常 “__flash__removeCallback”未定义

    使用场景结合artdialog弹出框使用时发生“__flash__removeCallback”未定义,原因在于artdialog基于iframe加载的uloadify,在关闭artdialog的时候 ...

  9. fzu 2107 Hua Rong Dao(状态压缩)

    Problem 2107 Hua Rong Dao Accept: 106    Submit: 197 Time Limit: 1000 mSec    Memory Limit : 32768 K ...

  10. Hadoop入门进阶课程5--MapReduce原理及操作

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博主为石山园,博客地址为 http://www.cnblogs.com/shishanyuan  ...