前言
最近学分组的时候,一直弄不明白,总感觉一头雾水,通过近3个小时的断点调试和log输出。 大概了解了一些表象,先记录。
案例是这个
求出每门课程参考学生成绩最高平均分的学生的信息:
课程,姓名和平均分,详细见MapReduce笔记-练习第二题第3小题
数据格式是这样的:
第一个是课程名称,总共四个课程,computer,math,english,algorithm,
第二个是学生姓名,后面是每次考试的分数
math,huangxiaoming,85,75,85,99,66,88,75,91
english,huanglei,85,75,85,99,66,88,75,91
…
结论
执行流程结论
- map每读一行就 write 到 context 一次,按照指定的
key
进行分发 map 把所有的数据都读完了之后,大概执行到
67%
的时候,开始进入CustomBean
,执行CustomBean
的compareTo()
方法,会按照自己写的规则一条一条数据比较上述都比较完毕之后,map阶段就结束了,此时来到了 reduce阶段,但是是到了
67%
了- 到了reduce阶段,直接进入了MyGroup中自定义的compare方法。
- MyGroup的
compare()
方法,如果返回非0, 就会进入 reduce 方法写出到context
MyGroup进入Reduce的条件是
- MyReduce中,如果compare的结果不等于0,也就是比较的2者不相同, 此时就进入Reduce, 写出到上下文
- 如果相同,会一直往下读,直到读到不同的, 此时写出读到上下文。
- 因为MyGroup会在Reduce阶段执行,而
CustomBean
中的compareTo()
是在map阶段执行,所以需要在CustomBean
中就把组排好序,此时分组功能才能正常运作
指定分组类MyGroup和不指定的区别
指定与不指定是指:在Driver类中,是否加上job.setGroupingComparatorClass(MyGrouper.class);
这一句。
- 指定分组类:
- 会按照分组类中,自定义的
compare()
方法比较,相同的为一组,分完一组就进入一次reduce方法
- 会按照分组类中,自定义的
- 不指定分组类:(目前存疑)
- 是否是按照key进行分组
- 如果是自定义类为key,是否是按照此key中值相同的分为一组
- 如果是hadoop内置类,是否是按照此类的值分组(Text-String的值,IntWritable-int值等..)
- 依然是走得以上这套分组逻辑,一组的数据读完才进入到Reduce阶段做归并
Log信息
CustomBean
中没有进行分组
, 组内排序
的log
1 | // ==================MyGroup中compare()方法======================= |
CustomBean
中做了分组&组内排序
的
1 | // **Bean中相同的组进行分数降序, 组进行字典排序,此时MyGroup中执行的** |
其它疑点
- 通过log可以看出来, MyGroup是在读到了不同的数据,才会进入到 reduce 类中写出;
- 但是 通过 断点调试时, 现象是,第一次读到了2个相同的,就去reduce去写出了;
- 后面再读的就不做写出操作,直到下一次读到2个相同的,再在reduce中写出。