为什么我可以使用SparkSQL显示一个dataframe,但不能将其写入json并得到“java.lang.OutOfMemoryError"

2024-06-26 21:01:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我用SparkSQL处理数据,我想把我的数据写成一个子文件。在

...
step12.show()
step12.repartition(10).coalesce(1).write.json('wasb://liu@cliubo.blob.core.windows.net/test_data_4')

step12是我的数据帧,但是我得到一个错误告诉我java.lang.OutOfMemoryError: Unable to acquire 65536 bytes of memory, got 0它没有意义,因为我可以显示这个数据帧。我使用Microsoft Azure中的群集,它是16Gb,我的原始数据大约是1Gb,而这个step12不会超过2Mb。在

为什么会这样?如何解决?在

^{pr2}$

Tags: 文件数据corejsonwindowsshowblobwrite
3条回答

在同一个数据帧上重新分区、合并会导致性能较差,并且可能会导致OOM错误。在

在应用重新分区/合并并使用以下命令检查每个分区中的行之前,我希望您检查step12 dataframe上的分区数。在

step12.partitions.size // lets say 50 partitons
step12.rdd.mapPartitions(iter => Array(iter.size).iterator, true).collect()

若您看到任何分区的行数非常少或为空,则可以使用coalesce减少相同数量的分区。 coalesce总是确保较少的洗牌发生,这样我们就能获得合理的性能。在

例如: 在50个分区中,有40个分区的行数为空或非常少。在

^{pr2}$

这将创建10个文件作为输出文件。在

注意:coalesce不会创建相同大小的输出文件。在

如果你想创建相同大小的文件,那么就用repartion。 但是,重新划分会造成更多的混乱,并带来糟糕的性能。在

我认为coalesce给你带来了麻烦。coalesce可避免完全洗牌。如果知道数量在减少,那么执行器就可以安全地将数据保存在最小数量的分区上,只将数据从额外的节点移到我们保留的节点上。所以,应该是这样的:

Node 1 = 1,2,3
Node 2 = 4,5,6
Node 3 = 7,8,9
Node 4 = 10,11,12

然后合并为2个分区:

^{pr2}$

所以在您的例子中,您将分区的数量减少到1,这会导致内存问题。我认为删除coalesce将解决outofmemory错误。在

首先,coalesce和{}非常相似。两者兼而有之,既尴尬又不必要。在

接下来,如果您查看coalesce的文档:

但是,如果您正在进行剧烈的合并,例如对numPartitions=1,这可能会导致您在比您喜欢的节点更少的节点上进行计算(例如,在numPartitions=1的情况下,只有一个节点)。为了避免这种情况,可以传递shuffle=true。这将添加一个shuffle步骤,但意味着当前的上游分区将并行执行(无论当前分区是什么)。

合并为1,因此可以尝试将shuffle标志设置为true。在

但我认为最重要的是不要只是尝试任何事情,而是要花时间了解各种操作的作用以及它们是如何工作的,以了解真正发生了什么。例如,我发现使用glom,它在“现实生活”中有一个合法的目的,当我想了解在我逐步扩展的过程中,在控制台中如何划分事物时,它也会对我非常有帮助。在

相关问题 更多 >