Spark:重新分区与partitionBy中的列参数顺序

时间:2018-01-20 12:58:50

标签: apache-spark dataframe apache-spark-sql partitioning

考虑的方法(Spark 2.2.1):

  1. DataFrame.repartition(采用partitionExprs: Column*参数的两个实现)
  2. DataFrameWriter.partitionBy
  3. 注意:这个问题不会问这些方法之间的区别

    来自partitionBy的{​​{3}}:

      

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

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

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

    来自repartition的{​​{3}}:

      

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

    根据我目前的理解,repartition在处理DataFrame时决定并行度。有了这个定义,repartition(numPartitions: Int)的行为很简单,但对于repartition带有partitionExprs: Column*个参数的其他两个实现,也不能说同样的。

    所有事情都说,我怀疑的是:

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

2 个答案:

答案 0 :(得分:6)

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

话虽如此,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查询,那么为并行执行提取的每个块是否包含与每个组中相同的数据?

取决于具体问题。

相关How to define partitioning of DataFrame?

答案 1 :(得分:-1)

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

:这些块物理映射到HDFS文件夹,并且能够存储子块和镶木地板/ *文件。

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

现在来回答。

Repartition(number_of_partitions,* columns):这将创建镶木地板文件,对数据进行混洗,并根据提供的列的不同组合值进行排序。因此,列的顺序在这里没有任何区别。您可以在后台提供任何顺序来获取这些列的所有可能值,对它们进行排序,然后将数据整理到文件中,这些文件的总和为 number_of_partitions

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

颜色A = [1,2,3,4,5]

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

colA-2

colA-3 。 。 。 如果您提供两列,则

colA-1 /        colB-1        colB-2        colB-3        。        

colA-2 /

colA-3 / 。 。

,在其中将存储实木复合地板文件,这些文件的数据将按父列值排序。该文件夹中的文件数将由(bucketBy)属性固定,该属性将进一步建议每个文件夹中的最大文件数。仅在pyspark 2.3和scala 1.6及更高版本中可用。