![](/img/trans.png)
[英]Apache Spark Dataframe - Issue with setting up a not-equal join
[英]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.我認為您應該在加入之前查看每個表中的分區數。 當Spark讀取文件時,它不一定保持與原始表(鑲木地板,csv或其他)相同數量的分區。 從csv讀取vs讀取HBase可能會創建不同數量的分區,這就是您看到性能差異的原因。 加入后,太大的分區變得更大,這會產生內存問題。 在Spark UI中查看每個任務的Peak Execution Memory。 這將讓您了解每個任務的內存使用情況。 我發現最好將它保持在1 Gb以下。
解決方案:在加入之前重新分區表。
廣告。 2也許不是這里的情況,但值得檢查。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.