Spark:repartition vs partitionBy 中列参数的顺序



考虑的方法(Spark 2.2.1):

  1. DataFrame.repartition(采用partitionExprs: Column*参数的两个实现)
  2. DataFrameWriter.partitionBy

注意:这个问题没有询问这些方法之间的区别

来自partitionBy文档:

如果指定,输出将布置在文件系统上,类似于Hive分区方案。例如,当我们按年和月对Dataset进行分区时,目录布局如下所示:

  • 年=2016/月=01/
  • 年=2016/月=02/

由此,我推断列参数的顺序将决定目录布局;因此它是相关的

来自repartition文档:

返回由给定分区表达式分区的新Dataset,使用spark.sql.shuffle.partitions作为分区数。生成的Dataset哈希分区的。

根据我目前的理解,repartition决定了处理DataFrame并行程度。有了这个定义,repartition(numPartitions: Int)的行为很简单,但对于其他两个采用partitionExprs: Column*参数的repartition实现来说,情况就不一样了。


综上所述,我的疑问如下:

  • partitionBy方法一样,列输入的顺序是否也与repartition方法相关?
  • 如果上述问题的答案是
    • :为并行执行提取的每个是否包含与我们在相同列上运行GROUP BYSQL查询时每个组中相同的数据?
    • :请解释repartition(columnExprs: Column*)方法的行为
  • repartition的第三次实现中同时拥有numPartitions: IntpartitionExprs: Column*参数有什么意义?

这两种方法之间的唯一相似之处是它们的名称。有用于不同的东西,有不同的机制,所以你根本不应该比较它们。

话虽如此,repartition使用以下方法对数据进行随机排序:

  • 对于partitionExprs,它使用spark.sql.shuffle.partitions对表达式中使用的列使用哈希分区程序。
  • 使用partitionExprsnumPartitions它的作用与上一个相同,但覆盖spark.sql.shuffle.partitions.
  • 有了numPartitions它只是使用RoundRobinPartitioning重新排列数据。

列输入的顺序也与重新分区方法相关?

是的。hash((x, y))一般与hash((y, x))不同。

df = (spark.range(5, numPartitions=4).toDF("x")
.selectExpr("cast(x as string)")
.crossJoin(spark.range(5, numPartitions=4).toDF("y")))
df.repartition(4, "y", "x").rdd.glom().map(len).collect()
[8, 6, 9, 2]
df.repartition(4, "x", "y").rdd.glom().map(len).collect()
[6, 4, 3, 12]

为并行执行提取的每个块是否包含与我们在相同列上使用 GROUP BY 运行 SQL 查询时每个组中相同的数据?

取决于确切的问题是什么。

  • 是的。 具有同一组列的GROUP BY将导致分区上相同的键逻辑分布。
  • 不。哈希分区程序可以将多个键映射到同一分区。GROUP BY只"看到"实际的组。

相关 如何定义数据帧的分区?

在回答这个问题之前,让我先向您介绍一下 Spark 中的一些概念。

block:这些物理映射到HDFS文件夹,能够存储子块和parquet/*文件。

拼接地板:数据存储压缩文件,在HDFS集群中常用于存储数据。

现在来回答。

重新分区(number_of_partitions, *列) : 这将创建镶木地板文件,其中数据根据所提供的列的不同组合值进行随机排序。 因此,列的顺序在这里没有任何区别。 您可以在后台提供任何顺序 Spark 将获取这些列的所有可能值,对它们进行排序并将数据排列在文件中,这些数据的总和将number_of_partitions

PartionBy(*columns):这与重新分区略有不同。 这将在 HDFS 中创建块或文件夹,参数中提供的列值不同。 所以假设:

Col A = [1,2,3,4,5]

在写入表 HDFS 时,它将创建文件夹名称 可乐A-1

可乐A-2

可乐A-3 . . . 如果您提供两列,则

可乐-1/ 乙二醇-1 ColB-2 科尔B-3 . .

可乐-2/

可乐-3/. . .

在此内部,它将存储镶木地板文件,这些文件将根据父列值对数据进行排序。 此文件夹中的文件数将由 (bucketBy) 属性固定,该属性将进一步建议每个文件夹中的最大文件数。 这仅在 PySpark 2.3 和 Scala 1.6 及更高版本中可用。

最新更新