-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[SPARK-28356][SQL] Do not reduce the number of partitions for repartition in adaptive execution #25121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPARK-28356][SQL] Do not reduce the number of partitions for repartition in adaptive execution #25121
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,12 +61,16 @@ case class ReduceNumShufflePartitions(conf: SQLConf) extends Rule[SparkPlan] { | |
| // If not all leaf nodes are query stages, it's not safe to reduce the number of | ||
| // shuffle partitions, because we may break the assumption that all children of a spark plan | ||
| // have same number of output partitions. | ||
| return plan | ||
| } | ||
|
|
||
| val shuffleStages = plan.collect { | ||
| case stage: ShuffleQueryStageExec => stage | ||
| case ReusedQueryStageExec(_, stage: ShuffleQueryStageExec, _) => stage | ||
| } | ||
| if (!shuffleStages.forall(_.canChangeNumPartition)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a comment to explain it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure |
||
| plan | ||
| } else { | ||
| val shuffleStages = plan.collect { | ||
| case stage: ShuffleQueryStageExec => stage | ||
| case ReusedQueryStageExec(_, stage: ShuffleQueryStageExec, _) => stage | ||
| } | ||
| val shuffleMetrics = shuffleStages.map { stage => | ||
| val metricsFuture = stage.mapOutputStatisticsFuture | ||
| assert(metricsFuture.isCompleted, "ShuffleQueryStageExec should already be ready") | ||
|
|
@@ -76,8 +80,6 @@ case class ReduceNumShufflePartitions(conf: SQLConf) extends Rule[SparkPlan] { | |
| // `ShuffleQueryStageExec` gives null mapOutputStatistics when the input RDD has 0 partitions, | ||
| // we should skip it when calculating the `partitionStartIndices`. | ||
| val validMetrics = shuffleMetrics.filter(_ != null) | ||
| // We may get different pre-shuffle partition number if user calls repartition manually. | ||
| // We don't reduce shuffle partition number in that case. | ||
| val distinctNumPreShufflePartitions = | ||
| validMetrics.map(stats => stats.bytesByPartitionId.length).distinct | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -574,22 +574,17 @@ class ReduceNumShufflePartitionsSuite extends SparkFunSuite with BeforeAndAfterA | |
| withSparkSession(test, 4, None) | ||
| } | ||
|
|
||
| test("Union two datasets with different pre-shuffle partition number") { | ||
| test("Do not reduce the number of shuffle partition for repartition") { | ||
| val test: SparkSession => Unit = { spark: SparkSession => | ||
| val dataset1 = spark.range(3) | ||
| val dataset2 = spark.range(3) | ||
|
|
||
| val resultDf = dataset1.repartition(2, dataset1.col("id")) | ||
| .union(dataset2.repartition(3, dataset2.col("id"))).toDF() | ||
| val ds = spark.range(3) | ||
| val resultDf = ds.repartition(2, ds.col("id")).toDF() | ||
|
|
||
| checkAnswer(resultDf, | ||
| Seq((0), (0), (1), (1), (2), (2)).map(i => Row(i))) | ||
| Seq((0), (1), (2)).map(i => Row(i))) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is just
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True. Good catch. |
||
| val finalPlan = resultDf.queryExecution.executedPlan | ||
| .asInstanceOf[AdaptiveSparkPlanExec].executedPlan | ||
| // As the pre-shuffle partition number are different, we will skip reducing | ||
| // the shuffle partition numbers. | ||
| assert(finalPlan.collect { case p: CoalescedShuffleReaderExec => p }.length == 0) | ||
| } | ||
| withSparkSession(test, 100, None) | ||
| withSparkSession(test, 200, None) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this? It only saves typing 4 characters....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed it.