在Hive里面,mapjoin是默认开启的,也就是说当join的表是小于默认配置25M时候,会自动将关联方式转化为mapjoin.当然这个small table的大小可以自行调节.走mapjoin的好处是,可以去掉mr框架中shuffle和reduce过程,让join的步骤只在map端处理,这样极大的提高了性能.
在Apache社区中HIVE-1642已经解决了这个issue,也就是根据表记录的大小自动将common join转换为mapjoin.
Hive实现的方式是在启动mapjoin时候,会启动一个本地的mr任务,先将小表从HDFS中读取到内存中并映射成哈希表,然后将哈希表序列化为哈希表文件,并将这个哈希表文件上传到分布式缓存中,接着将这些文件发送给每个Mapper。最后,当MR任务启动时候,会去拿到这些缓存文件进行join,输出相应的结果。这样小表只读取了一次,而且join的过程也没有shuffle和reduce,减少了数据在网络传输等过程。
这里,通过MR的框架,来实现一个简易版的mapjoin.
比如,构造一个交易数据,数据结构如下:

还有一个商品表,数据结构如下:
如果说交易数据表数据量很大,而商品定义表一般数据量比较小,通过实现mapjoin方式来得到商品交易的数据.
具体实现的代码如下所示:
首先在驱动程序里面,定义好MR的map任务和输出结果,由于采用mapjoin所以没有定义reduce任务,并且设置了reduce个数为0.

2.在定义的缓存类中,在setup方法中,将放在缓存中的数据(商品表)添加到Hashmap中保存,
在map方法中,将交易表的数据读取进来与hashmap中的数据做匹配,最后将结果输出.

从运行的结果看,任务并没有发生溢写,也没有reduce阶段。

接下来,通过DEBUG这个任务时候,可以看到在任务submit后,生成getSplits方法里面,
只生成了一个切片文件,这里切片的计算方法还是跟前面分析得到一样,每次切片都会计算剩下文件的大小/splitsize的值是否大于1.1,如果大于则按照splitsize来切分,如果不大于,则切分为一片.


当调用createSplitFiles后,会在对应的目录(默认在staging里面)看到生成的splits切片文件信息


根据切片数量,所以map数量也只有1个.





