PySpark:使用binaryFiles()函数读取二进制文件时进行分区

时间:2018-05-29 14:11:37

标签: apache-spark pyspark rdd binaryfiles partitioning

sc = SparkContext("Local")
rdd = sc.binaryFiles(Path to the binary file , minPartitions = 5).partitionBy(8)

sc = SparkContext("Local")
rdd = sc.binaryFiles(Path to the binary file , minPartitions = 5).repartition(8)

使用上述任一代码,我试图在我的RDD中制作8个分区{其中,我希望数据在所有分区上均匀分布} 。当我打印 {rdd.getNumPartitions()} 时,显示的分区数量仅为8,但在 Spark UI 上,我观察到虽然制作了8个分区但所有整个二进制文件数据只放在一个分区上。

注意: minPartition 属性不起作用。即使在设置minPartitions = 5之后,RDD中创建的分区数也只有1。因此,使用了partitionBy / repartition函数。

这是期望的行为还是我错过了什么?

2 个答案:

答案 0 :(得分:6)

Spark 2.4 + ,该问题应已解决,请参见此答案下方的@Rahul评论。

Spark 2.1-2.3 minPartitions的{​​{1}}参数将被忽略。请参见Spark-16575commit changes to function setMinPartitions()。请注意,提交中的更改更改了函数中不再使用binaryFiles()的方式!

如果您正在使用minPartitions读取多个二进制文件,则输入文件将基于以下内容合并为分区:

  • binaryFiles(),默认为128 MB
  • spark.files.maxPartitionBytes,默认4 MB
  • spark.files.openCostInBytes
  • 您输入的总大小

前三个配置项描述为here。请参阅上面的提交更改以查看实际计算。

我有一个场景,我希望每个输入分区最多40 MB,因此每个任务40 MB ...以在解析时增加并行度。 (Spark将128 MB放入每个分区,这降低了我的应用程序的速度。)在调用spark.default.parallelism之前,我将spark.files.maxPartitionBytes设置为40 M:

binaryFiles()

对于仅一个输入文件,@ user9864979的答案是正确的:不能仅使用spark = SparkSession \ .builder \ .config("spark.files.maxPartitionBytes", 40*1024*1024) 将单个文件拆分为多个分区。


使用 Spark 1.6 读取多个文件时,binaryFiles()参数确实有效,您必须使用它。否则,您将遇到Spark-16575问题:所有输入文件将仅被读取到两个分区中!

您会发现,Spark通常会为您提供比您要求的更少的输入分区。我有一种情况,我希望每两个输入二进制文件有一个输入分区。我发现将minPartitions设置为“输入文件数* 7/10”可以大致满足我的需求。
我有另一种情况,我希望每个输入文件都有一个输入分区。我发现将minPartitions设置为“输入文件数* 2”可以满足我的需求。

minPartitions

Spark 1.5 行为:每个输入文件只有一个分区。

答案 1 :(得分:2)

TL; DR 这是预期的行为。

由于您使用binaryFiles读取文件,因此文件的整个内容将作为单个记录加载,并且不能跨多个分区拆分单个记录。这里没有什么可以分发的。