200个默认分区的spark.sql.shuffle.partitions难题

时间:2018-08-21 13:39:27

标签: apache-spark

由于帖子改组,分区,JOIN,AGGR等原因,在许多帖子中都有这样的语句-如下所示,以某种形式显示:

...通常,只要您执行Spark sql聚合或对数据进行混洗的联接,这就是结果分区的数量= 200。 这是由spark.sql.shuffle.partitions设置的。 ...

所以,我的问题是:

  • 我们的意思是说,例如,如果我们为DF设置了分区765,
    • 该处理针对765个分区进行,但是输出已合并/标准地重新分区为200-在这里指单词 resulting
    • 或者在合并,AGGR之前合并/重新分区为200个分区后,是否使用200个分区进行处理?

我问,因为我从未见过清晰的观点。

我做了以下测试:

// genned ad DS of some 20M short rows
df0.count
val ds1 = df0.repartition(765)
ds1.count
val ds2 = df0.repartition(765)
ds2.count

sqlContext.setConf("spark.sql.shuffle.partitions", "765")
// The above not included on 1st run, the above included on 2nd run.

ds1.rdd.partitions.size
ds2.rdd.partitions.size

val joined = ds1.join(ds2, ds1("time_asc") === ds2("time_asc"), "outer") 
joined.rdd.partitions.size
joined.count
joined.rdd.partitions.size

在第一个测试中-未定义 sqlContext.setConf(“ spark.sql.shuffle.partitions”,“ 765”),结果是处理分区和num分区是200.即使SO post 45704156指出它可能不适用于DF,也就是DS。

在第二项测试中-定义 sqlContext.setConf(“ spark.sql.shuffle.partitions”,“ 765”),得到的处理分区和num分区为765即使SO post 45704156声明它可能不适用于DF-这是DS。

2 个答案:

答案 0 :(得分:1)

Spark.sql.shuffle.partitions是一个参数,它决定在进行诸如连接或聚合之类的混洗(即节点之间的数据移动位置)时进行分区的数量。另一部分spark.default.parallelism将根据您的数据大小和最大块大小进行计算,在HDFS中为128mb。因此,如果您的作业没有进行任何改组,它将考虑默认的并行度值,或者如果您使用的是rdd,则可以自己设置。改组发生时将需要200。

Val df = sc.parallelize(List(1,2,3,4,5),4).toDF() df.count()//这将使用4个分区

Val df1 = df df1.except(df).count //将生成200个具有2个阶段的分区

答案 1 :(得分:1)

这是您的两种猜测的结合。

假设您有一组具有M个分区的输入数据,并且将shuffle分区设置为N。

执行联接时,spark会在所有M个分区中读取您的输入数据,并根据N个分区的键将数据重新排序。想象一下一个简单的hashpartitioner,应用于键的hash函数几乎看起来像A = hashcode(key)%N,然后将此数据重新分配给负责处理Ath分区的节点。每个节点可以负责处理多个分区。

混洗后,节点将工作以将数据聚合到它们负责的分区中。由于此处无需进行其他改组,因此节点可以直接产生输出。

因此,总而言之,您的输出将合并到N个分区,但是之所以合并,是因为它在N个分区中处理,而不是因为spark应用了一个额外的混洗阶段来将输出数据专门重新分区为N。