我正在使用Spark(版本1.6.1)处理JSON文件以生成两个JSON文件。输入文件的大小约为30~40G(100M记录)。对于生成的文件,较大的文件大约为10G~15G(30M记录),较小的文件大约为500M~750M(1.5M记录)。两个结果文件都面临以下问题:
我为数据帧调用了“sort”方法,之后执行“重新分区”将结果合并到一个文件中。然后我检查了生成的文件,在一个间隔中找到了订单记录,但整个文件没有全局排序。例如文件中最后一条记录(行号为1.9M)的密钥(由3列构成)是“(ou7QDj48c,014,075)”,但文件中的中间记录的密钥(行号375K)是“( pzwzh5vm8,003,023)“
pzwzh5vm8 003 023
...
ou7QDj48c 014 075
当我使用相对较小的输入源(输入文件400K行)在本地测试代码时,根本不会发生这种情况。
我的具体代码如下所示:
big_json = big_json.sort($"col1", $"col2", $"col3", $"col4")
big_json.repartition(1).write.mode("overwrite").json("filepath")
有人可以提出建议吗?谢谢。
(我也注意到this thread讨论了类似的问题,但到目前为止还没有一个好的解决方案。如果这种现象真的是由重新分区操作引起的,那么任何人都可以帮我有效地将数据帧转换为单个JSON文件没有将其转换为RDD,同时保持排序顺序?谢谢)
解决方案:
非常感谢@manos @eliasah和@pkrishna的帮助。在阅读了你的评论之后,我曾考虑过使用coalesce,但在调查了它的表现后,我放弃了这个想法。
最终解决方案是:对数据帧进行排序并写入JSON,无需任何重新分区或合并。完成整个工作后,请调用下面的HDFS命令
hdfs dfs -getmerge /hdfs/file/path/part* ./local.json
这个命令比我的想象要好得多。它既不需要太多时间也不需要太多空间,并且给我一个很好的单个文件。我刚刚在巨大的结果文件中使用了head
和tail
,它似乎完全有序。
答案 0 :(得分:7)
在排序操作 之后,重新分区 会发生什么。
repartition
随机重新调整RDD中的数据,以创建更多或更少的分区,并在它们之间进行平衡。这总是随机播放网络上的所有数据。
在幕后,它使用coalesce
和shuffle
来重新分配数据。
这就是您的数据不再排序的原因。
您可以查看reference的代码。
答案 1 :(得分:3)
由于您的示例中分区计数设置为1,这意味着分区将减少为1。
为了减少rdd中的分区数量,spark提供了一个转换合并(使用shuffle = false)来保留订单。
作为eliasah,提到使用coalesce在引擎盖下重新分配。它使用shuffle = true调用coalesce。因此,可以使用coalesce变换代替使用shuffle = false重新分区。