簡體   English   中英

加入一個巨大而巨大的火花數據框

[英]Joining a large and a ginormous spark dataframe

我有兩個數據幀,df1 有 600 萬行,df2 有 10 億行。

我嘗試過標准的df1.join(df2,df1("id")<=>df2("id2")) ,但內存不足。

df1 太大,無法放入廣播連接。

我什至嘗試過布隆過濾器,但它也太大了,無法放入廣播中,但仍然有用。

我嘗試過的唯一不會出錯的方法是將 df1 分成 300,000 個行塊並在 foreach 循環中與 df2 連接。 但這比它可能需要的時間長一個數量級(可能是因為它太大而無法作為持久化,導致它重做分割到那個點)。 重新組合結果也需要一段時間。

你是如何解決這個問題的?

一些注意事項:

df1 是 df2 的子集。 df1=df2.where("fin<1").selectExpr("id as id2").distinct()我對 df2 中的所有行都感興趣,這些行的 ID 曾經有一個 fin<1,這意味着我不能一步到位。

df2 中大約有 2 億個唯一 ID。

以下是一些相關的火花設置:

spark.cores.max=1000
spark.executor.memory=15G
spark.akka.frameSize=1024
spark.shuffle.consolidateFiles=false
spark.task.cpus=1
spark.driver.cores=1
spark.executor.cores=1
spark.memory.fraction=0.5
spark.memory.storageFraction=0.3
spark.sql.shuffle.partitions=10000
spark.default.parallelism=10000

我得到的錯誤是:

16/03/11 04:36:07 ERROR LiveListenerBus: SparkListenerBus has already stopped! Dropping event SparkListenerTaskEnd(11,1,ResultTask,FetchFailed(BlockManagerId(68dcb91c-1b45-437d-ac47-8e8c1e4bc386-S199, mapr, 46487),3,176,4750,org.apache.spark.shuffle.FetchFailedException: java.io.FileNotFoundException: /tmp/mesos/work/slaves/68dcb91c-1b45-437d-ac47-8e8c1e4bc386-S199/frameworks/c754216b-bf80-4d84-97f1-2e907030365e-2545/executors/16/runs/5a5a01c5-205e-4380-94d3-7fa0f6421b85/blockmgr-ea345692-05bb-4f42-9ba1-7b93311fb9d4/0e/shuffle_3_340_0.index (No such file or directory)

Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 465 in stage 6.3 failed 4 times, most recent failure: Lost task 465.3 in stage 6.3 (TID 114448, mapr): java.lang.OutOfMemoryError: Direct buffer memory

我認為你有一個太大的分區問題(可能是由於更大的數據)你可以嘗試一些方法:

  1. 嘗試將spark.sql.shuffle.partitions定義為2048甚至更多(默認值為200)。 加入你的df-s時會有洗牌。 嘗試使用此參數,以便更大數據/此參數的總體積約為64Mb-100Mb(取決於文件格式)。 通常,您應該在spark UI中看到每個任務(每個分區)處理“正常”數據量(最大64MB-100MB)

  2. 如果第一個不起作用我可以建議加入RDD api。 將您的df轉換為RDD。 然后通過HashPartitioner(分區數)對兩個RDD進行分區。 當我應該如前所述計算分區數時。

  3. 最近火花開發者添加了新的選項:你可以將巨大的表存入N個桶(即存儲它為連接做好准備)。 存在的限制很少,但它可以完全消除混亂的巨大數據。 bucketBy僅受saveAsTable api支持而不保存。 在您獲取數據並將其分解后,在下一次迭代中,您可以將此數據作為外部表加載,同時提供存儲規范(請參閱https://docs.databricks.com/spark/latest/spark-sql/language-manual/ create-table.html

    CREATE TABLE ginormous --...在這里你必須指定模式USING PARQUET CLUSTERED BY(a,b,c)INTO N桶LOCATION'hdfs:// your-path'

然后,當您將巨型表加載為分段表時,可以加載大表並將其重新分配到相同數量的桶和相同列(df.repartition(N,a,b,c))

你可以嘗試設置,spark.shuffle.memoryFraction = 0.0嗎?

這將導致shuffle將所有內容溢出到磁盤,並且您永遠不會收到OOM錯誤

如果符合您的要求,您也可以使用雙程方法。 首先,重新分區數據並使用分區表(dataframe.write.partitionBy())持久化。 然后,在循環中串行連接子分區,“追加”到同一個最終結果表。

高效的pyspark加入

如果這種方法適合您,請告訴我。如果您有更好的選擇加入兩個大型數據框並希望共享,請告訴我。 :-)

暫無
暫無

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

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