考虑的方法(Spark 2.2.1
):
DataFrame.repartition
(采用partitionExprs: Column*
参数的两个实现)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 BY
SQL
查询时每个组中相同的数据? - 是:请解释
repartition(columnExprs: Column*)
方法的行为
- 否:为并行执行提取的每个块是否包含与我们在相同列上运行
- 在
repartition
的第三次实现中同时拥有numPartitions: Int
和partitionExprs: Column*
参数有什么意义?
这两种方法之间的唯一相似之处是它们的名称。有用于不同的东西,有不同的机制,所以你根本不应该比较它们。
话虽如此,repartition
使用以下方法对数据进行随机排序:
- 对于
partitionExprs
,它使用spark.sql.shuffle.partitions
对表达式中使用的列使用哈希分区程序。 - 使用
partitionExprs
和numPartitions
它的作用与上一个相同,但覆盖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 及更高版本中可用。