簡體   English   中英

(Spark skewed join)如何使用高度重復的密鑰加入兩個沒有內存問題的大型Spark RDD?

[英](Spark skewed join) How to join two large Spark RDDs with highly duplicated keys without memory issues?

上一個問題中 ,我試圖通過避免使用join避免 Spark join內存問題

在這個新問題中,我正在使用join ,但試圖修復內存問題

這些是我的兩個RDD:

  1. productToCustomerRDD:
    大小:非常大,可能有數百萬個不同的鍵
    使用HashPartitioner對密鑰進行分區
    有些密鑰會高度重復,有些則不會。

     (toast, John) (butter, John) (toast, Jane) (jelly, Jane) 
  2. productToCountRDD:
    大小:非常大,可能有數百萬個不同的鍵,太大而無法broadcast
    使用HashPartitioner對密鑰進行分區
    密鑰是唯一的 ,價值是購買產品的客戶數量。

     (toast, 2) (butter, 1) (jelly, 1) 

我想加入這兩個RDD,結果將是:

  1. customerToProductAndCountRDD:

     (toast, (John, 2)) (butter, (John, 1)) (toast, (Jane, 2)) (jelly, (Jane, 1)) 

如果我使用productToCustomerRDD.join(productToCountRDD)加入兩個RDD,我會在兩個分區上獲得一個OutOfMemoryError (數千個)。 在Spark UI中,我注意到在包含join的階段,在“ Input Size / Records列中,所有分區都有4K700K的記錄數。 除了產生OOM的兩個分區之外的所有分區:一個有9M記錄,一個有6M記錄。

據我所知, 為了加入,需要對具有相同密鑰的對進行混洗並移動到同一分區 (除非它們先前已被密鑰分區)。 但是,由於某些密鑰非常頻繁(例如:幾乎每個客戶都在數據集中購買的產品),大量數據可能會在join期間或在repartition之前移動到一個分區。加入。

我理解正確嗎?
有辦法避免這種情況嗎?
是否有一種方法可以在沒有同一分區上一個重復密鑰的所有數據的情況下join

實際上,這是Spark中的標准問題,稱為“傾斜連接”:連接的一側是傾斜的,這意味着它的一些鍵比其他鍵更頻繁。 可以在這里找到一些對我來說無效的答案。

我所使用的策略是由啟發GraphFrame.skewedJoin()定義的方法在這里及在使用ConnectedComponents.skewedJoin() 這里 通過使用廣播連接加入最頻繁的密鑰和使用標准連接的較不頻繁的密鑰來執行連接。

在我的示例(OP)中, productToCountRDD已包含有關鍵頻率的信息。 所以它是這樣的:

  • 過濾productToCountRDD只保留高於固定閾值的計數,並將collectAsMap()到驅動程序。
  • 將此映射廣播給所有執行程序。
  • productToCustomerRDD拆分為兩個RDD:在廣播映射中找到的鍵(頻繁鍵)和不是(不頻繁鍵)的鍵。
  • 頻繁鍵的連接是使用mapToPair執行的,從廣播映射中獲取count
  • 不經常密鑰的連接是通過join執行的。
  • 最后使用union來獲得完整的RDD。

我的第一個問題是:你真的需要theese的詳細數據嗎? 你真的需要知道jhon買了2個toatat等等嗎? 我們處於大數據環境中,並且我們處理大量數據,因此有時聚合是減少基數並在分析和性能方面獲得良好結果的好方法。 因此,如果您想知道產品銷售的次數,您可以使用pairRDD(產品,計數)[這樣您將為每個產品提供一個元素]或者如果您想了解用戶偏好,您可以使用pairRDD(用戶,購買產品列表)[以這種方式,您將為每個用戶提供一個元素]。 如果你真的需要知道從Jhon購買吐司,你為什么要在不同的重新分區中分割吐司鍵? 通過這種方式,您無法計算全局結果,因為在每個chunck中,您只有一條關於鍵的信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM