【问题标题】:PySpark: Partitioning while reading a binary file using binaryFiles() functionPySpark:使用 binaryFiles() 函数读取二进制文件时进行分区
【发布时间】:2018-11-08 05:42:37
【问题描述】:
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 函数。

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

【问题讨论】:

    标签: apache-spark pyspark rdd binaryfiles partitioning


    【解决方案1】:

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

    Spark 2.1-2.3,binaryFiles() 的 minPartitions 参数被忽略。请参阅Spark-16575 和commit changes to function setMinPartitions()。请注意,在提交更改中minPartitions 不再在函数中使用!

    如果您使用binaryFiles() 读取多个二进制文件,输入文件将根据以下内容合并为分区:

    • spark.files.maxPartitionBytes,默认 128 MB
    • spark.files.openCostInBytes,默认 4 MB
    • spark.default.parallelism
    • 输入的总大小

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

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

    spark = SparkSession \
       .builder \
       .config("spark.files.maxPartitionBytes", 40*1024*1024)
    

    对于只有一个输入文件,@user9864979 的答案是正确的:不能仅使用 binaryFiles() 将单个文件拆分为多个分区。


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

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

    Spark 1.5 行为binaryFiles():每个输入文件都有一个分区。

    【讨论】:

    • 很好的答案。看起来这已在 spark 2.4 (issues.apache.org/jira/browse/SPARK-22357) 中得到修复。同时,将 spark.files.maxPartitionBytes 设置为较低的值似乎是诱使 spark 使用多个分区的解决方法。
    【解决方案2】:

    TL;DR这是预期的行为。

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

    【讨论】:

    • 但是根据 Spark 的官方文档, binaryFiles() 函数中的 minPartition 参数决定了输入数据的最小分割数。因此,如果 minPartitions 设置为 5,则输入数据应至少分成五个分区。对吗?
    • @user_19 不是真的。它确定最小分区数。这并不是说分区将是非空的或数据将在分区之间均匀分布。如果您至少有 num-partitions 文件,那么您可以期待更均匀的分布(实际上没有任何保证)。如果您想使用单个输入文件分发数据,那么您使用了错误的功能。
    • 从 Spark 2.1 开始,minPartitions 参数被忽略——请参阅我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2019-04-13
    相关资源
    最近更新 更多