在使用orderBy
之后,spark如何确定分区数?我一直以为所得到的数据帧具有spark.sql.shuffle.partitions
,但事实并非如此:
val df = (1 to 10000).map(i => ("a",i)).toDF("n","i").repartition(10).cache
df.orderBy($"i").rdd.getNumPartitions // = 200 (=spark.sql.shuffle.partitions)
df.orderBy($"n").rdd.getNumPartitions // = 2
在两种情况下,spark都+- Exchange rangepartitioning(i/n ASC NULLS FIRST, 200)
起作用,那么第二种情况下的结果分区数如何为2?
答案 0 :(得分:3)
spark.sql.shuffle.partitions
用作上限。分区的最终数量为1 <= partitions <= spark.sql.shuffle.partition
。
如前所述,Spark中的排序通过RangePartitioner
进行。它试图实现的是将数据集划分为大致相等范围的指定数量(spark.sql.shuffle.partition
)。
保证分区后相等的值将在同一分区中。值得检查RangePartitioning
(不是公共API的一部分)类文档:
...
ordering
中的表达式求值相同的所有行都将在同一分区中
并且如果不同的排序值的数量小于所需的分区数量,即,可能的范围数量小于spark.sql.shuffle.partition
,则最终将得到较少的分区数量。另外,这是RangePartitioner
Scaladoc的引用:
RangePartitioner创建的实际分区数可能 在以下情况下,该参数与partitions参数不同 采样记录的数量小于分区的值。
回到您的示例,n
是一个常量("a"
),无法分区。另一方面,i
可以有10,000个可能的值,并被划分为200(=spark.sql.shuffle.partition
)个范围或分区。
请注意,这仅适用于DataFrame / Dataset API。使用RDD的sortByKey
时,可以明确指定分区数,或者Spark将使用当前分区数。
另请参阅:
答案 1 :(得分:1)
除了查看范围分区以进行排序外,我还进行了各种测试,以便从经验上更深入地进行研究-这是问题的症结所在。参见How does range partitioner work in Spark?。
已尝试使用问题示例中的“ n”的1个不同值和“ n”的1个以上的不同值,然后对 df.orderBy($“使用各种数据帧大小n“):
分配的额外分区几乎总是空的事实使我认为编码中存在某种计算错误,换句话说就是一个小虫子。
我基于以下简单测试,该测试确实返回了我认为应该认为是适当数量的分区的RR:
val df_a1 = (1 to 1).map(i => ("a",i)).toDF("n","i").cache
val df_a2 = (1 to 1).map(i => ("b",i)).toDF("n","i").cache
val df_a3 = (1 to 1).map(i => ("c",i)).toDF("n","i").cache
val df_b = df_a1.union(df_a2)
val df_c = df_b.union(df_a3)
df_c.orderBy($"n")
.rdd
.mapPartitionsWithIndex{case (i,rows) => Iterator((i,rows.size))}
.toDF("partition_number","number_of_records")
.show(100,false)
返回:
+----------------+-----------------+
|partition_number|number_of_records|
+----------------+-----------------+
|0 |1 |
|1 |1 |
|2 |1 |
+----------------+-----------------+
此边界示例计算非常简单。只要对任何“ n”使用 1到2 或 1 .. N ,就会产生多余的空分区:
+----------------+-----------------+
|partition_number|number_of_records|
+----------------+-----------------+
|0 |2 |
|1 |1 |
|2 |1 |
|3 |0 |
+----------------+-----------------+
排序要求给定“ n”或一组“ n”的所有数据都在同一分区中。