由于帖子改组,分区,JOIN,AGGR等原因,在许多帖子中都有这样的语句-如下所示,以某种形式显示:
...通常,只要您执行Spark sql聚合或对数据进行混洗的联接,这就是结果分区的数量= 200。 这是由spark.sql.shuffle.partitions设置的。 ...
所以,我的问题是:
我问,因为我从未见过清晰的观点。
我做了以下测试:
// 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。
答案 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。