企業大資料平臺MapReduce應用之Join實踐!

大資料頻道發表於2018-11-02

在《Hadoop從入門到精通》大型專題的上半部分(專題連結見文末),我們講解了Hadoop基本原理並且知道如何在Hadoop中組織、移動和儲存資料。接下來,我們將探討如何簡化企業大資料技術應用。本章主要研究大資料模式,針對最佳化MapReduce操作技術,例如對大型資料集進行連線和排序,這些技術將讓任務執行更快,並允許更有效地使用計算資源。

MapReduce包含許多強大的功能,本章重點介紹連線、排序和取樣。這三種模式很重要,因為它們是被頻繁使用的大資料操作,並且滿足企業叢集獲取更優效能的目標。

6.1 Joining

Join是用於將關係組合在一起的操作。在MapReduce中,Join適用於組合兩個或更多資料集的情況,例如,希望將使用者(從OLTP資料庫中提取)與日誌檔案(包含使用者活動詳細資訊)組合在一起。在以下情況中,將資料集組合在一起是有用的,例如:

  • 希望根據使用者人口統計資訊(例如使用者習慣差異,比較青少年和30多歲使用者的差異)來彙總資料。

  • 希望向未在指定天數內使用該網站的使用者傳送電子郵件。

  • 希望建立反饋迴圈來檢查使用者瀏覽習慣,允許系統向使用者推薦以前未探索的站點功能。

所有這些場景都要求將資料集連線在一起,兩種最常見的Join型別是內連線和外連線。內連線比較關係L和R中的所有元組,並在滿足連線謂詞時生成結果。相反,外連線不需要基於連線謂詞匹配元組,即使不存在匹配也可保留L或R的記錄。

圖6.1 不同型別的Join策略,顯示為維恩圖。陰影區域顯示在連線中保留的資料。

本節,我們將介紹MapReduce的三種Join策略,支援兩種最常見的Join型別(內部和外部)。透過利用MapReduce排序—合併架構,可以在map或reduce端進行連線:

  • Repartition join——將兩個或多個大型資料集連線在一起的情況下減少側連線;

  • Replication join ——map端連線,適用於其中一個資料集足夠小可進行快取的情況;

  • Semi-join——map側連線,其中一個資料集太大而無法容納到記憶體中,但經過某些過濾後可以減少到適合記憶體的大小

Join data

這些技術都將利用兩個資料集來連線使用者和日誌。使用者資料包含使用者名稱,年齡和狀態。完整資料集如下:

日誌資料集顯示可以從應用程式或Web伺服器日誌中提取一些基於使用者的活動。資料包括使用者名稱,操作和源IP地址,以下是完整的資料集:

讓我們先看一下應該根據資料選擇哪種Join方法。

實踐:為資料選擇最佳Join策略

本節介紹的每種Join策略都有不同的優點和缺點,確定哪種策略最適合正在使用的資料可能具有挑戰性。該技術可以檢視資料中的不同特徵,並使用該資訊選擇Join資料的最佳方法。

問題

選擇Join資料的最佳方法。

解決方案

使用資料驅動的決策樹來選擇最佳的Join策略。

討論

圖6.2顯示了可以使用的決策樹。

圖6.2 用於選擇Join策略的決策樹

決策樹可歸納為以下三點:

  • 如果某個資料集小到足以放入mapper記憶體中,則maponly複製的Join是有效的。

  • 如果兩個資料集都很大,並且其中一個可以透過預過濾縮小與另一個資料集的不匹配,則Semi-join效果更好。

  • 如果無法預處理資料且資料太大而無法快取 - 這意味著必須在reducer中執行Join 

無論選擇哪種策略,應該在Join中執行的最基本活動之一是使用過濾器和投影。

過濾器,投影和下推

在mapper中有效使用過濾器和投影可以減少MapReduce中使用和溢位的資料量。此技術還包括一種稱為下推的更高階最佳化,這可以進一步改善資料管道。

問題

正在處理大量資料,並且希望有效管理輸入資料以最佳化作業。

解決方案

過濾並投影資料,僅包含將在工作中使用的資料。

討論

過濾和投影資料是在Join資料時以及在處理資料時可以進行的最大最佳化。這是一種適用於任何OLAP活動的技術,它在Hadoop中同樣有效。

為什麼過濾和投影如此重要? 他們減少了處理管道需要處理的資料量。使用較少的資料非常重要,尤其是當跨網路和磁碟邊界推送資料時。MapReduce中隨機播放步驟非常昂貴,因為資料正在寫入本地磁碟和整個網路,因此更少的位元組數就意味著作業和MapReduce框架的工作量更少,這意味著CPU,磁碟和網路裝置上有更少的負載。

圖6.3 使用過濾器和投影來減少資料大小

過濾器和投影應儘可能靠近資料來源執行,在MapReduce中,這項工作最好在mapper中執行。以下程式碼顯示了過濾器示例,該過濾器排除了30歲以下的使用者,並且只投影其名稱和狀態:

在連線中使用過濾器的挑戰是:所加入的所有資料集都可能包含要過濾的欄位。如果是這種情況,請檢視使用Bloom過濾器解決此挑戰。

投影和謂詞下推

在使用可以基於下推來跳過記錄或整個塊的儲存格式時,將投影和謂詞下推儲存格式進一步過濾非常有效。

表6.1儲存格式及其下推支援

關於下推

很明顯,Parquet的一大優勢是能夠支援兩種型別的下推。如果正在處理大型資料集並且只定期處理記錄和欄位的子集,那麼應該將Parquet視為儲存格式。

6.1.1 map端Join

首先介紹在mapper中執行Join。如果資料可以支援map側Join,那麼將是最佳Join策略。對比mapper和reducer之間重排資料的開銷,減小資料集的大小以便可以在map端Join是明智的。

本節將介紹三種不同風格的map側Join。一是其中一個資料集已足夠小可以在儲存器快取記憶體的情況下工作良好;二是要求在過濾掉兩個資料集中存在連線鍵的記錄之後,一個資料集可以適合儲存器;三是適用於以特定方式對檔案進行排序和分佈的情況。

實踐:Join資料,其中一個資料集可以適合記憶體

replicated join是一個map端連線,它從其函式中獲取名稱。最小的資料集將複製到所有map主機,其操作取決於一個事實,即Join資料集之一足夠小,可以快取在記憶體中。

問題

希望對資料執行Join,其中一個資料集適合mapper記憶體。

解決方案

使用分散式快取較小資料集,並在較大資料集流式傳輸到mapper時執行Join。

討論

使用分散式快取將小資料集複製到執行map tasks2的節點,並使用每個map任務的初始化方法將其載入到雜湊表中。使用從大資料集反饋到map函式的每個記錄中的鍵來查詢小資料集雜湊表,並在大資料集和小資料集中與Join值匹配的所有記錄之間執行Join。 圖6.4顯示了該方法在MapReduce中的工作原理。

圖6.4僅map的複製Join

以下程式碼執行此Join:


要執行此Join,首先需要將要加入的兩個檔案複製到HDFS中的主目錄:

接下來,執行作業並在完成後檢查其輸出:

Hive

透過在執行之前配置作業,可以將Hive連線轉換為map端連線。重要的是最大的表是查詢中的最後一個表,因為這是Hive將在mapper中流式傳輸的表(其他表將被快取):

不再強調map-join提示Hive 0.11實現了一些更改,這些更改表面上刪除了map-join提示作為SELECT語句的一部分,但是不清楚在哪些情況下不再需要提示。全連線或右外連線不支援map端Join,它們將作為重新分割槽Join執行(reduce端連線)。

總結

內部和外部Join都可以使用複製Join來支援。此技術實現了內部Join,因為只發出了兩個資料集中具有相同鍵的記錄。要將其轉換為外部Join,可以流式傳輸到mapper中的值,這些值在雜湊表中沒有相應的條目,可以類似地跟蹤與流式map記錄匹配的雜湊表條目並使用方法在map任務結束時從雜湊表中發出與任何map輸入都不匹配的記錄。

在資料集足夠小以便在記憶體中快取的情況下,有沒有辦法進一步最佳化map側Join?現在是時候看看Semi-join了。

實踐:在大型資料集上執行Semi-join

想象一下,正在使用兩個大型資料集,例如使用者日誌和來自OLTP資料庫的使用者資料。這些資料集中的任何一個都不足夠小以在map記憶體中快取,因此必須自己執行reducer端連線。問自己一個問題:如果要刪除與其他資料集中記錄不匹配的所有記錄,其中一個資料集是否適合map端記憶體?

在示例中,日誌中顯示的使用者很可能只佔OLTP資料庫整體使用者集的一小部分,因此透過刪除日誌中未顯示的所有OLTP使用者,可以將資料集縮小到適合記憶體的大小。如果是這種情況,Semi-join就是解決方案。 圖6.5顯示了執行Semi-join所需執行的三個MapReduce作業。

問題

希望將大型資料集Join在一起,同時避免混洗和排序階段的開銷。

解決方案

在此技術中,我們將使用三個MapReduce作業將兩個資料集連線在一起,以避免reducer端連線的開銷。此技術在處理大型資料集的情況下非常有用,過濾掉與其他資料集不匹配的記錄,可以將作業減小到可以放入任務記憶體的大小。

討論

該技術將分解圖6.5中所示的三個作業。

Job1

第一個MapReduce作業的功能是生成一組存在於日誌檔案中的唯一使用者名稱,可以透過讓map函式執行使用者名稱的投影來執行此操作,然後使用reducer發出使用者名稱。要減少map和reduce階段之間傳輸的資料量,將使map任務快取HashSet中的所有使用者名稱,並在清理方法中發出HashSet值。圖6.6顯示了此作業的流程。

圖6.5構成Semi-join的三個MapReduce作業

圖6.6 Semi-join中的第一個作業生成一組存在於日誌檔案中的唯一使用者名稱。

以下程式碼顯示了MapReduce作業:

第一個作業的結果是出現在日誌檔案中的一組唯一使用者。

Job2

第二步是精心過濾MapReduce作業,其目標是從使用者資料集中刪除日誌資料中不存在的使用者。 這是一個僅map端作業,使用複製的Join來快取日誌檔案中顯示的使用者名稱,並將其與使用者資料集Join起來。Job1的唯一使用者輸出將遠遠小於整個使用者資料集,這使其成為快取的自然選擇。圖6.7顯示了此作業的流程。

圖6.7 Semi-join中的第二個作業從日誌資料中缺少的使用者資料集中刪除使用者。

Job 3

在最後一步中,我們將把Job 2生成的過濾使用者與原始使用者日誌結合起來。過濾後的使用者現在應該足夠少以留在記憶體中,允許將它們放入分散式快取中,圖6.8顯示了此作業的流程。

圖6.8 Semi-join中的第三個作業將Job2生成的使用者與原始使用者日誌組合在一起。

執行程式碼並檢視前面每個步驟生成的輸出:

輸出顯示Semi-join和最終Join輸出中作業的邏輯進展。

總結

在這種技術中,我們研究瞭如何使用Semi-join將兩個資料集組合在一起。Semi-join構造涉及比其他Join更多的步驟,但即使在處理大型資料集時,它也是使用map側Join的有效方式(需要注意的是,其中一個資料集必須縮小到適合記憶體的大小))。

實踐:加入預分類和預分割槽資料

Map側Join是最有效的技術,前兩個map側策略都要求其中一個資料集可以載入到記憶體中。 如果正在使用無法按照先前技術的要求縮小到較小尺寸的大型資料集,該怎麼辦? 在這種情況下,複合map端連線可能是可行的,但僅當滿足以下所有要求時:

  • 沒有任何資料集可以完整地載入到記憶體中。

  • 資料集全部按Join鍵排序。

  • 每個資料集具有相同數量的檔案。

  • 每個資料集中的檔案N包含相同的連線金鑰K.

  • 每個檔案都小於HDFS塊的大小,因此不會拆分分割槽。 或者,資料的輸入拆分不會拆分檔案。

圖6.9顯示了有助於複合Join的已排序和分割槽檔案的示例,此技術將介紹如何在作業中使用複合Join。

問題

希望對已排序的分割槽資料執行map端Join。

圖6.9 用作複合Join的輸入已排序檔案示例

解決方案

使用與MapReduce捆綁在一起的CompositeInputFormat。

討論

CompositeInputFormat非常強大,支援內部和外部聯接。 以下示例顯示如何對資料執行內部聯接:

複合Join要求輸入檔案按鍵排序(在我們的示例中是使用者名稱),因此在執行示例之前,需要對這兩個檔案進行排序並將它們上傳到HDFS:

接下來,執行作業並在完成後檢查其輸出:

Hive

Hive支援稱為排序合併Join的map端連線,其操作方式與此技術的操作方式大致相同。要求在兩個表中對所有鍵進行排序,並且必須將表格劃分為相同數量的bucket。需要指定一些配置,並使用MAPJOIN提示來啟用此行為:

總結

複合Join實際上支援N路連線,因此可以Join兩個以上的資料集。但是,所有資料集必須符合同一組限制,由於每個mapper使用兩個或多個資料輸入,因此資料位置只能與其中一個資料集一起存在,因此其餘資料集必須從其他資料節點流式傳輸。對於在執行Join之前資料必須存在的方式,此Join肯定是限制性的,但如果資料已經按照這種方式佈局,那麼這是一種加入資料並避免基於reducer的shuffle開銷的好方法。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545816/viewspace-2218254/,如需轉載,請註明出處,否則將追究法律責任。

相關文章