Spark数据框加入问题

时间:2019-03-10 22:46:36

标签: scala apache-spark hbase

下面的代码段工作正常。(读取CSV,读取Parquet并相互连接)

//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则不能。在具有125 GB内存的100个工作节点集群上运行此文件。因此内存不是问题。

我的问题是文件和Hbase都具有相同的数据,并且都可以读取并能够显示()数据。但是为什么只有Hbase失败了。我正在努力了解此代码可能出了什么问题。任何建议将不胜感激。

2 个答案:

答案 0 :(得分:2)

在提取数据时,spark并不知道从HBase检索到的行数,因此选择的策略是排序合并联接。

因此,它尝试对执行程序之间的数据进行排序和重新排序。

为避免此问题,我们可以同时使用广播联接,而不必使用键列(它显示了代码片段中的最后一条语句)对df2中的数据进行排序和混排。

无论如何绕过它(因为它只有一行),我们可以对要填充的列使用Case表达式。

示例:

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

答案 1 :(得分:1)

有时我也会遇到这个错误。通常在连接期间spark尝试广播大表时会发生这种情况(当spark的优化器低估表的大小或统计信息不正确时,就会发生这种情况)。由于没有提示强制进行排序合并联接(How to hint for sort merge join or shuffled hash join (and skip broadcast hash join)?),因此唯一的选择是通过设置spark.sql.autoBroadcastJoinThreshold= -1

来禁用广播联接。