我用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}$
在同一个数据帧上重新分区、合并会导致性能较差,并且可能会导致OOM错误。在
在应用重新分区/合并并使用以下命令检查每个分区中的行之前,我希望您检查step12 dataframe上的分区数。在
若您看到任何分区的行数非常少或为空,则可以使用coalesce减少相同数量的分区。 coalesce总是确保较少的洗牌发生,这样我们就能获得合理的性能。在
例如: 在50个分区中,有40个分区的行数为空或非常少。在
^{pr2}$这将创建10个文件作为输出文件。在
注意:coalesce不会创建相同大小的输出文件。在
如果你想创建相同大小的文件,那么就用repartion。 但是,重新划分会造成更多的混乱,并带来糟糕的性能。在
我认为coalesce给你带来了麻烦。coalesce可避免完全洗牌。如果知道数量在减少,那么执行器就可以安全地将数据保存在最小数量的分区上,只将数据从额外的节点移到我们保留的节点上。所以,应该是这样的:
然后合并为2个分区:
^{pr2}$所以在您的例子中,您将分区的数量减少到1,这会导致内存问题。我认为删除coalesce将解决outofmemory错误。在
首先,}非常相似。两者兼而有之,既尴尬又不必要。在
coalesce
和{接下来,如果您查看
coalesce
的文档:“但是,如果您正在进行剧烈的合并,例如对numPartitions=1,这可能会导致您在比您喜欢的节点更少的节点上进行计算(例如,在numPartitions=1的情况下,只有一个节点)。为了避免这种情况,可以传递shuffle=true。这将添加一个shuffle步骤,但意味着当前的上游分区将并行执行(无论当前分区是什么)。“
合并为1,因此可以尝试将
shuffle
标志设置为true。在但我认为最重要的是不要只是尝试任何事情,而是要花时间了解各种操作的作用以及它们是如何工作的,以了解真正发生了什么。例如,我发现使用
glom
,它在“现实生活”中有一个合法的目的,当我想了解在我逐步扩展的过程中,在控制台中如何划分事物时,它也会对我非常有帮助。在相关问题 更多 >
编程相关推荐