Scala Spark数据帧连接问题

Scala Spark数据帧连接问题,scala,apache-spark,hbase,Scala,Apache Spark,Hbase,下面的代码片段工作正常。(阅读CSV,阅读拼花,并相互连接) 很奇怪下面的代码片段不起作用。(阅读Hbase、阅读拼花地板并相互连接)(区别在于阅读Hbase) 错误:原因:org.apache.spark.SparkException:作业因阶段失败而中止:56个任务的序列化结果的总大小(1024.4 MB)大于spark.driver.maxResultSize(1024.0 MB) 然后我添加了spark.driver.maxResultSize=5g,然后又出现了另一个错误,Java堆空

下面的代码片段工作正常。(阅读CSV,阅读拼花,并相互连接)

很奇怪下面的代码片段不起作用。(阅读Hbase、阅读拼花地板并相互连接)(区别在于阅读Hbase)

错误:原因: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并进行计数()。程序运行良好。下面是代码片段

//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个工作节点群集上运行此操作,每个群集上有125 GB内存。所以记忆不是问题


我这里的问题是文件和Hbase都有相同的数据,并且都可以读取和显示数据。但为什么只有Hbase失败了呢。我正在努力理解这段代码可能出了什么问题。如果您有任何建议,我们将不胜感激。

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

因此,它尝试在执行器之间对数据进行排序和洗牌

为了避免这个问题,我们可以同时使用broadcast-join,而不习惯使用key列对from-df2中的数据进行排序和洗牌,key列显示了代码片段中的最后一条语句

然而,为了绕过这一点(因为它只有一行),我们可以对要填充的列使用Case表达式

例如:

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

我有时也在与这个错误作斗争。这种情况通常发生在spark在连接期间尝试广播一个大表时(当spark的优化器低估了表的大小,或者统计数据不正确时)。由于没有强制排序合并联接()的提示,唯一的选项是通过设置
spark.sql.autoBroadcastJoinThreshold=-1禁用广播联接。当联接过程中内存出现问题时,这通常意味着以下两个原因之一:

  • 数据帧中的分区太少(分区太大)
  • 在您连接的关键点上的两个数据帧中有许多重复项,连接会爆炸您的内存
  • 公元1年。我认为您应该在加入之前查看每个表中的分区数量。当Spark读取文件时,它不一定保留与原始表(拼花、csv或其他)相同数量的分区。从csv读取和从HBase读取可能会创建不同数量的分区,这就是为什么您会看到性能上的差异。太大的分区在连接后变得更大,这会造成内存问题。查看Spark UI中每个任务的峰值执行内存。这将让您了解每个任务的内存使用情况。我发现最好将其保持在1GB以下

    解决方案:在联接之前重新分区表


    广告2可能不是这里的情况,但值得一查。

    谢谢您的回复。只是一个信息。hbase表将来可能会增加,但不会超过100行。我无法按hbaseKey操作。你能再解释一下你提到的case表达式吗?为什么分区的数量在广播连接中很重要?这与驾驶员记忆有什么关系?
    //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")
    
    df.withColumn(
    "newCol"
    ,when(col("df2col1").eq(lit(hbaseKey))
        ,lit(hbaseValueCol1))
     .otherwise(lit(null))