簡體   English   中英

Spark數據幀加入問題

[英]Spark dataframe Join issue

下面的代碼片段工作正常。 (閱讀CSV,閱讀實木復合地板並互相加入)

//Reading csv file -- getting three columns: Number of records: 1
 df1=spark.read.format("csv").load(filePath) 

df2=spark.read.parquet(inputFilePath)

//Join with Another table : Number of records: 30 Million, total 
columns: 15
df2.join(broadcast(df1), col("df2col1") === col("df1col1")  "right")

它在下面的代碼片段下工作不起作用。 (閱讀Hbase,閱讀Parquet並互相加入)(差異是從Hbase讀取)

//Reading from Hbase (It read from hbase properly -- getting three columns: Number of records: 1
 df1=read from Hbase code
 // It read from Hbase properly and able to show one record.
 df1.show

df2=spark.read.parquet(inputFilePath)

//Join with Another table : Number of records: 50 Million, total 
columns: 15
df2.join(broadcast(df1), col("df2col1") === col("df1col1")  "right")

錯誤 :由以下原因引起:org.apache.spark.SparkException:作業因階段失敗而中止:56個任務(1024.4 MB)的序列化結果總大小大於spark.driver.maxResultSize(1024.0 MB)

然后我添加了spark.driver.maxResultSize = 5g,然后又出現了另一個錯誤,Java堆空間錯誤(在ThreadPoolExecutor.java上運行)。 如果我在Manager中觀察內存使用情況,我會看到該用法一直持續到達50GB左右,此時會發生OOM錯誤。 因此無論出於何種原因,用於執行此操作的RAM量比我嘗試使用的RDD的大小大約10倍。

如果我將df1保留在內存和磁盤中並執行count()。 程序運行正常。 代碼段如下

//Reading from Hbase -- getting three columns: Number of records: 1
 df1=read from Hbase code

**df1.persist(StorageLevel.MEMORY_AND_DISK)
val cnt = df1.count()**

df2=spark.read.parquet(inputFilePath)

//Join with Another table : Number of records: 50 Million, total 
columns: 15
df2.join(broadcast(df1), col("df2col1") === col("df1col1")  "right")

它適用於文件,即使它具有相同的數據,但不與Hbase一起使用。 在100個worknode集群上運行此程序,每個集群上有125 GB的內存。 所以記憶不是問題。

我的問題是文件和Hbase都有相同的數據,並且都讀取並能夠顯示()數據。 但為什么只有Hbase失敗。 我很難理解這段代碼可能出現的問題。 任何建議將不勝感激。

當提取數據時,spark不知道從HBase檢索的行數,因此選擇的策略是排序合並連接。

因此,它試圖對執行程序中的數據進行排序和混洗。

為了避免這個問題,我們可以使用廣播連接,同時我們不會使用密鑰列對來自df2的數據進行排序和混洗,密鑰列顯示代碼片段中的最后一個語句。

但是要繞過這個(因為它只有一行),我們可以使用Case表達式來填充列。

例:

df.withColumn(
"newCol"
,when(col("df2col1").eq(lit(hbaseKey))
    ,lit(hbaseValueCol1))
 .otherwise(lit(null))

我有時也在努力解決這個錯誤。 通常這種情況發生在spark嘗試在連接期間廣播一個大表時(當spark的優化器低估了表的大小或統計信息不正確時)。 由於沒有提示強制排序合並連接( 如何提示排序合並連接或混洗散列連接(以及跳過廣播散列連接)? ),唯一的選擇是通過設置spark.sql.autoBroadcastJoinThreshold= -1來禁用廣播連接spark.sql.autoBroadcastJoinThreshold= -1

當我在加入期間遇到內存問題時,通常意味着以下兩個原因之一:

  1. 數據幀中的分區太少(分區太大)
  2. 您加入的密鑰上的兩個數據框中有許多重復項,並且連接會破壞您的內存。

廣告1.我認為您應該在加入之前查看每個表中的分區數。 當Spark讀取文件時,它不一定保持與原始表(鑲木地板,csv或其他)相同數量的分區。 從csv讀取vs讀取HBase可能會創建不同數量的分區,這就是您看到性能差異的原因。 加入后,太大的分區變得更大,這會產生內存問題。 在Spark UI中查看每個任務的Peak Execution Memory。 這將讓您了解每個任務的內存使用情況。 我發現最好將它保持在1 Gb以下。

解決方案:在加入之前重新分區表。

廣告。 2也許不是這里的情況,但值得檢查。

暫無
暫無

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

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