我们开始在我们的团队中尝试使用spark。 在减少Spark中的工作量之后,我们希望将结果写入S3,但是我们希望避免收集Spark结果。 目前,我们正在将文件写入RDD的Spark forEachPartition,但是这导致了很多小文件。我们希望能够将数据聚合到几个文件中,该文件按写入文件的对象数量进行分区。 因此,例如,我们的总数据为1M个对象(这是恒定的),我们想产生400K个对象文件,而我们当前的分区产生大约20k个对象文件(这对于每个作业而言变化很大)。理想情况下,我们要生成3个文件,每个文件包含400k,400k和200k,而不是50个文件的2万个对象
有人建议吗?
我的想法是让每个分区处理每个分区应该写入的索引,方法是假设每个分区将大致产生相同数量的对象。 因此,例如,分区0将写入第一个文件,而分区21将写入第二个文件,因为它将假定对象的起始索引为20000 * 21 = 42000,该索引大于文件大小。 分区41将写入第三个文件,因为它大于2 *文件大小限制。 但是,这不一定总是达到理想的400k文件大小限制,更多情况下是近似值。
我知道有合并,但是据我了解,合并是根据所需分区数减少分区数。我想要的是根据每个分区中对象的数量合并数据,有没有很好的方法呢?
答案 0 :(得分:0)
我们决定只处理生成的文件数,并确保每个文件包含少于一百万个订单项
答案 1 :(得分:0)
您想要做的是将文件重新划分为三个分区。每个分区将拆分大约333k条记录。该分区将是近似的,每个分区将不完全是333,333。我不知道一种获取所需的400k / 400k / 200k分区的方法。
如果您有DataFrame`df',则可以重新分区为n个分区,
df.repartition(n)
由于您希望每个分区有最大数量或记录,因此我建议您这样做(您不指定Scala或pyspark,因此我将使用Scala;您可以在pyspark中进行相同操作):
val maxRecordsPerPartition = ???
val numPartitions = (df.count() / maxRecordsPerPartition).toInt + 1
df
.repartition(numPartitions)
.write
.format('json')
.save('/path/file_name.json')
这将确保您的分区小于maxRecordsPerPartition。