Hive中的Join可分為Common Join(Reduce階段完成join)和Map Join(Map階段完成join)
一、Map Join作用及原理
作用簡單來說,在Map階段進行join,而不是Common Join那樣在Reduce階段按照join列進行分發后在每個Reduce節點上進行join,一來省去Shuffle這個代價昂貴的階段,二來不需要分發也就沒有傾斜的問題。
ps:關於Shuffle的過程可讀上篇文章:https://www.cnblogs.com/rango-lhl/p/14292709.html
①、具體過程:
在Map 端進行join,其原理是broadcast join,即把小表作為一個完整的驅動表來進行join操作。通常情況下,要連接的各個表里面的數據會分布在不同的Map中進行處理。即同一個Key對應的Value可能存在不同的Map中。這樣就必須等到 Reduce中去連接。要使MapJoin能夠順利進行,那就必須滿足這樣的條件:除了一份表的數據分布在不同的Map中外,其他連接的表的數據必須在每個Map中有完整的拷貝。Map Join會把小表全部讀入內存中,在Map階段直接拿另外一個表的數據和內存中表數據做匹配 (這時可以使用Distributed Cache將小表分發到各個節點上,以供Mapper加載使用),由於在map時進行了join操作,省去了reduce運行的效率也會高很多。
②、拓展閱讀:
早期版本中,當成千上萬個 Mapper 同時從 HDFS 將小的連接表讀入內存時,連接表很容易成為性能瓶頸,導致 Mapper 在讀取操作期間超時。后期Hive優化思路是在原始 Join 的 MapReduce 任務之前創建一個新的 MapReduce 本地任務。這個新任務是將小表數據從 HDFS 上讀取到內存中的哈希表中。讀完后,將內存中的哈希表序列化為哈希表文件。在下一階段,當 MapReduce 任務啟動時,會將這個哈希表文件上傳到 Hadoop 分布式緩存中,該緩存會將這些文件發送到每個 Mapper 的本地磁盤上。因此,所有 Mapper 都可以將此持久化的哈希表文件加載回內存,並像之前一樣進行 Join。優化后,小表只需要讀取一次。此外,如果多個 Mapper 在同一台機器上運行,則分布式緩存只需將哈希表文件的一個副本發送到這台機器上。(拓展部分拜讀於該文http://cloud.tencent.com/developer/article/1481780)
二、應用場景
結合原理可知,Map Join的適用大表Join小表及不等值的鏈接操作。
-
關於小表的大小,由參數 hive.mapjoin.smalltable.filesize來決定,該參數表示小表的總大小,默認值為25000000字節,即25M。實際中此參數允許的最大值可以修改,但是一般最大不能超過1GB
-
Hive0.7之前,需要使用hint提示/*+mapjoin(table)*/才會執行MapJoin,否則執行Common Join,但在0.7版本之后,默認自動會轉換Map Join,由參數 hive.auto.convert.join來控制,默認為true。
學習交流,有任何問題還請隨時評論指出交流。