十一、理解MapReduce的二次排序功能,包括自定义数据类型、分区、分组、排序

一、二次排序不仅可以对key进行排序,同时也可以对value中的某个字段进行排序。
有两种过程


组合排序—>分区(可选)—>分组


分区—> 排序(二次) —>分组


下面以第一种方式来进行说明:
1、Map阶段,排序,进行key和value组成组合的key,例如(k+v,v)。分别对组合key中的k和v进行分区排序。设置自定义数据类型并实现WritableComparable接口,自定义数据类型作为组合的新key,实现compareTo方法,分别对k和v比较分区排序。
2、Reduce阶段,分组,构造一个key对应的value迭代器。这时要用到分组,使用jobjob.setGroupingComparatorClass设置的分组函数类。只要这个比较器比较的两个key相同,他们就属于同一个组,它们的value放在一个value迭代器,而这个迭代器的key使用属于同一个组的所有key的第一个key。最后就是进入Reducer的reduce方法,reduce方法的输入是所有的(key和它的value迭代器)。同样注意输入与输出的类型必须与自定义的Reducer中声明的一致。
3、分区(可选)设置分区类继承Partitioner类,在map阶段的最后,会先调用job.setPartitionerClass对这个List进行分区,保证要对原来的key进行分区,每个分区映射到一个reduce。每个分区内又调用job.setSortComparatorClass设置的key比较函数类排序。可以看到,这本身就是一个二次排序。如果没有通过job.setSortComparatorClass设置key比较函数类,则使用key的实现的compareTo方法。
4、排序时要注意全正数或全负数进行比较。
5、编码实现二次排序功能
代码在附件:
SecondarySortMapReduce.java
PairWritable.java
FirstPartitioner.java
FirstGroupingComparator.java
二、理解MapReduce Join 的几种方式,编码实现Reduce Join

Mapreduce 有三种join方式


在reduce端进行连接


在Reudce端进行连接是MapReduce框架进行表之间join操作最为常见的模式:
Map端的主要工作:为来自不同表(文件)的key/value对打标签以区别不同来源的记录。然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
reduce端的主要工作:在reduce端以连接字段作为key的分组已经完成,我们只需要在每一个分组当中将那些来源于不同文件的记录(在map阶段已经打标志)分开,最后进行笛卡尔积就可以了。


在Map端进行连接

使用场景:一张表十分小、一张表很大。
用法:在提交作业的时候先将小表文件放到该作业的DistributedCache中,然后从DistributeCache中取出该小表进行join key / value解释分割放到内存中(可以放大Hash Map等等容器中)。然后扫描大表,看大表中的每条记录的join key /value值是否能够在内存中找到相同join key的记录,如果有则直接输出结果。


SemiJoin

SemiJoin就是所谓的半连接,其实仔细一看就是reduce join的一个变种,就是在map端过滤掉一些数据,在网络中只传输参与连接的数据不参与连接的数据不必在网络中进行传输,从而减少了shuffle的网络传输量,使整体效率得到提高,其他思想和reduce join是一样的。将小表中参与join的key单独抽出来通过DistributedCach分发到相关节点,然后将其取出放到内存中(可以放到HashSet中),在map阶段扫描连接表,将join key不在内存HashSet中的记录过滤掉,让那些参与join的记录通过shuffle传输到reduce端进行join操作,其他的和reduce join都是一样的。

ReduceJoin.java
JoinWritable.java



猜你喜欢

转载自blog.csdn.net/zipo/article/details/54947630