Postgresql Spark优化-连接-任务数量非常少-OOM

Postgresql Spark优化-连接-任务数量非常少-OOM,postgresql,amazon-web-services,scala,apache-spark,out-of-memory,Postgresql,Amazon Web Services,Scala,Apache Spark,Out Of Memory,我的spark应用程序失败,出现以下错误:退出状态:143。诊断:根据请求终止容器。退出代码为143 这是我在检查容器日志时得到的结果:java.lang.OutOfMemoryError:java堆空间 我的应用程序主要是获取一个表,然后连接从aws S3中读取的不同表: var result = readParquet(table1) val table2 = readParquet(table2) result = result.join(table2 , result(primar

我的spark应用程序失败,出现以下错误:
退出状态:143。诊断:根据请求终止容器。退出代码为143

这是我在检查容器日志时得到的结果:
java.lang.OutOfMemoryError:java堆空间

我的应用程序主要是获取一个表,然后连接从aws S3中读取的不同表:

var result = readParquet(table1)  
val table2 = readParquet(table2)

result = result.join(table2 , result(primaryKey) === table2(foreignKey))

val table3 = readParquet(table3)

result = result.join(table3 , result(primaryKey) === table3(foreignKey))

val table4 = readParquet(table4)

result = result.join(table4 , result(primaryKey) === table4(foreignKey))
等等

当我尝试使用以下方法将结果数据帧保存到postgresql时,我的应用程序失败:

result.toDF(df.columns.map(x => x.toLowerCase()): _*).write
  .mode("overwrite")
  .format("jdbc")
  .option(JDBCOptions.JDBC_TABLE_NAME, table)
  .save()
在我失败的加入阶段,我的任务数量非常少:4个执行者有6个任务

为什么我的舞台能创造2个工作岗位

第一个是用426任务完成的:

第二个是失败的:

我的意见是:

dynamicAllocation = true  
num core = 2
driver memory = 6g
executor memory = 6g
max num executor = 10
min num executor = 1
spark.default.parallelism = 400
spark.sql.shuffle.partitions = 400
我尝试了更多的资源,但遇到了相同的问题:

 num core = 5
 driver memory = 16g
 executor memory = 16g
 num executor = 20
我认为,即使默认的分区数为400,所有数据都会进入同一个分区/执行器,这会导致OOM错误

我试过(没有成功): persit数据
broadcastJoin,但我的表不够小,无法在末尾播放它。
重新分区到更高的数字(4000)在每个联接之间进行计数以执行操作:

我的主表接缝增长非常快:
(行数)40->68->7304->946832->123032864->246064864->(之后的时间太长)
但是,数据量非常小

如果我看一下任务指标,一件有趣的事情是我的数据接缝倾斜(我真的不确定)
在最后一次计数操作中,我可以看到约120个任务执行操作,约10MB的输入数据用于100条记录和12秒,而其他3880个任务完全不执行任何操作(3ms,0条记录16B(元数据?):


驱动程序内存=16g内存太高,不需要。仅当通过(collect())等操作需要掌握大量数据时才使用。如果是这种情况,请确保增加spark.maxResult.size

你可以做以下事情

--在读取文件readParquet(表1)时进行重新分区。重新分区(x)。如果其中一个表很小,则可以广播该表并删除连接,而不是使用mapPartition并使用广播变量作为查找缓存

(或)

--选择均匀分布的列,并使用该列相应地重新划分表。

通过查看以上统计数据,我需要强调两点。您的作业有很高的调度延迟,这是由太多的任务和任务统计信息造成的。很少有统计信息是以10字节的输入数据启动的,很少有统计信息是以9MB的数据启动的。。。。显然,这里存在数据偏斜。。。正如您所说,第一个任务完成时有426个任务,但如果重新分区计数为4000,则应该启动更多任务


请看。。。获取更多信息。

驱动程序内存=16g内存太高,不需要。仅当通过(collect())等操作需要掌握大量数据时才使用。如果是这种情况,请确保增加spark.maxResult.size

你可以做以下事情

--在读取文件readParquet(表1)时进行重新分区。重新分区(x)。如果其中一个表很小,则可以广播该表并删除连接,而不是使用mapPartition并使用广播变量作为查找缓存

(或)

--选择均匀分布的列,并使用该列相应地重新划分表。

通过查看以上统计数据,我需要强调两点。您的作业有很高的调度延迟,这是由太多的任务和任务统计信息造成的。很少有统计信息是以10字节的输入数据启动的,很少有统计信息是以9MB的数据启动的。。。。显然,这里存在数据偏斜。。。正如您所说,第一个任务完成时有426个任务,但如果重新分区计数为4000,则应该启动更多任务


请看。。。获取更多信息。

driver memory=16g内存开销太大,当您需要通过(collect())等操作来掌握大量数据时,不需要使用它,例如在读取文件readParquet时执行重新分区(表1)。重新分区(x)。。。如果其中一个表很小,那么您可以广播该表并删除join use mapPartition并使用广播变量作为查找缓存。请提供您的表大小以获得更好的建议这与PostgreSQL有何关系?@kavetiraviteja感谢提供的信息,我将使用密钥加密来解决我的问题。您可以将您的评论作为答案发布,我会接受。驱动程序内存=16g的内存开销太大,当您有大量数据要通过(collect())等操作来掌握时,不需要使用它。读取文件readParquet时执行重新分区(表1)。重新分区(x)。。。如果其中一个表很小,那么您可以广播该表并删除join use mapPartition并使用广播变量作为查找缓存。请提供您的表大小以获得更好的建议这与PostgreSQL有何关系?@kavetiraviteja感谢提供的信息,我将使用密钥加密来解决我的问题。你可以把你的评论作为回答,我会接受的。