1. 程式人生 > >hadoop實現Join的幾種方法

hadoop實現Join的幾種方法

1) reduce side join

reduce side join是一種最簡單的join方式,其主要思想如下:

在map階段,map函式同時讀取兩個檔案File1和File2,為了區分兩種來源的key/value資料對,對每條資料打一個標籤 (tag),
比如:tag=0表示來自檔案File1,tag=2表示來自檔案File2。即:map階段的主要任務是對不同檔案中的資料打標籤。

在reduce階段,reduce函式獲取key相同的來自File1和File2檔案的value list, 然後對於同一個key,對File1和File2中的資料進行join(笛卡爾乘積)。
即:reduce階段進行實際的連線操作。

2) map side join

之所以存在reduce side join,是因為在map階段不能獲取所有需要的join欄位,即:同一個key對應的欄位可能位於不同map中。Reduce side join是非常低
效的,因為shuffle階段要進行大量的資料傳輸。

Map side join是針對以下場景進行的優化:兩個待連線表中,有一個表非常大,而另一個表非常小,以至於小表可以直接存放到記憶體中。這樣,我們可以將
小表複製多 份,讓每個map task記憶體中存在一份(比如存放到hash table中),然後只掃描大表:對於大表中的每一條記錄key/value,在hash table中
查詢是否有相同的key的記錄,如果有,則連線後輸出即可。

為了支援檔案的複製,Hadoop提供了一個類DistributedCache,使用該類的方法如下:

(1)使用者使用靜態方法DistributedCache.addCacheFile()指定要複製的檔案,它的引數是檔案的URI(如果是 HDFS上的檔案,可以這樣:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode埠 號)。JobTracker在作業啟動之前會獲取這個URI列表,並將相應的檔案拷貝到各個TaskTracker的本地磁碟上。(2)使用者使用 DistributedCache.getLocalCacheFiles()方法獲取檔案目錄,並使用標準的檔案讀寫API讀取相應的檔案。

3) SemiJoin

SemiJoin,也叫半連線,是從分散式資料庫中借鑑過來的方法。它的產生動機是:對於reduce side join,跨機器的資料傳輸量非常大,這成了join操作的一個瓶頸,如果能夠在map端過濾掉不會參加join操作的資料,則可以大大節省網路IO。

實現方法很簡單:選取一個小表,假設是File1,將其參與join的key抽取出來,儲存到檔案File3中,File3檔案一般很小,可以放 到記憶體中。在map階段,使用DistributedCache將File3複製到各個TaskTracker上,然後將File2中不在File3中的 key對應的記錄過濾掉,剩下的reduce階段的工作與reduce side join相同。

更多關於半連線的介紹,可參考:半連線介紹:

4) reduce side join + BloomFilter

在某些情況下,SemiJoin抽取出來的小表的key集合在記憶體中仍然存放不下,這時候可以使用BloomFiler以節省空間。

BloomFilter最常見的作用是:判斷某個元素是否在一個集合裡面。它最重要的兩個方法是:add() 和contains()。最大的特點是不會存在false negative,即:如果contains()返回false,則該元素一定不在集合中,但會存在一定的true negative,即:如果contains()返回true,則該元素可能在集合中。

因而可將小表中的key儲存到BloomFilter中,在map階段過濾大表,可能有一些不在小表中的記錄沒有過濾掉(但是在小表中的記錄一定不會過濾掉),這沒關係,只不過增加了少量的網路IO而已。