-
Notifications
You must be signed in to change notification settings - Fork 28.3k
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-30036][SQL] Fix: REPARTITION hint does not work with order by #26946
Conversation
Change-Id: I9ec887eece29abed048192b559f7d69a9e67afe3
Change-Id: If6b4c1f818c38b1862f69acc63f79feea127bbee
Change-Id: Ieb757a218588e2f35efd1b0eac4d076fb75eb1c8
I think we should add check at |
ok to test |
@ulysses-you Adding RangePartitioning doesn't happen in optimizer, thus we can't check this in |
Test build #115563 has finished for PR 26946 at commit
|
case (ShuffleExchangeExec(partitioning: RoundRobinPartitioning, child, _), | ||
distribution: OrderedDistribution) => | ||
ShuffleExchangeExec( | ||
distribution.createPartitioning(partitioning.numPartitions), child) |
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.
Could you update like the following, @stczwd ?
- case (ShuffleExchangeExec(partitioning: RoundRobinPartitioning, child, _),
- distribution: OrderedDistribution) =>
- ShuffleExchangeExec(
- distribution.createPartitioning(partitioning.numPartitions), child)
+ case (ShuffleExchangeExec(partitioning, child, _), distribution) =>
+ ShuffleExchangeExec(distribution.createPartitioning(partitioning.numPartitions), child)
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.
You means this should work in other Partitioning? Let me run some test for it.
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.
thanks, i have change my code
DummySparkPlan(outputPartitioning = partitioning))) | ||
val outputPlan = EnsureRequirements(spark.sessionState.conf).apply(inputPlan) | ||
assert(outputPlan.find{ | ||
case e: ShuffleExchangeExec => e.outputPartitioning.isInstanceOf[RoundRobinPartitioning] |
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.
- case e: ShuffleExchangeExec => e.outputPartitioning.isInstanceOf[RoundRobinPartitioning]
+ case ShuffleExchangeExec(_: RoundRobinPartitioning, _, _) => true
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.
good
partitioning, | ||
DummySparkPlan(outputPartitioning = partitioning))) | ||
val outputPlan = EnsureRequirements(spark.sessionState.conf).apply(inputPlan) | ||
assert(outputPlan.find{ |
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.
.find{
-> .find {
.
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.
done
I updated the PR description a little, @stczwd . |
@@ -55,6 +55,10 @@ case class EnsureRequirements(conf: SQLConf) extends Rule[SparkPlan] { | |||
child | |||
case (child, BroadcastDistribution(mode)) => | |||
BroadcastExchangeExec(mode, child) | |||
case (ShuffleExchangeExec(partitioning: RoundRobinPartitioning, child, _), |
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.
How about use Partitioning
instead of RoundRobinPartitioning
. Since we already support this SELECT /*+ REPARTITION(5, a) */ * FROM test ORDER BY a
.
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.
thanks, I will change it
@@ -421,6 +421,24 @@ class PlannerSuite extends SharedSparkSession { | |||
} | |||
} | |||
|
|||
test("SPARK-30036: EnsureRequirements replace Exchange " + | |||
"if child has SortExec and RoundRobinPartitioning") { |
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.
How about just saying Remove unnecessary RoundRobinPartitioning
in the test title? Also, can you make the PR title obivious, too?
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.
Good for test title, thanks.
But it is not suitable for PR title, there are other situations in this titile.
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.
How about Avoid RoundRobinPartitioning that EnsureRequirements Redundantly adds
?
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.
Because HashPartitioning should also be concerned.
@dongjoon-hyun thanks |
Change-Id: I6b102f32b4084625875b395990e8ac4673c56bac
Test build #115598 has finished for PR 26946 at commit
|
val outputPlan = EnsureRequirements(spark.sessionState.conf).apply(inputPlan) | ||
assert(outputPlan.find { | ||
case ShuffleExchangeExec(_: RoundRobinPartitioning, _, _) => true | ||
case _ => false}.isEmpty, |
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.
nit:
...find {
case ...
case ...
}.isEmpty
val outputPlan = EnsureRequirements(spark.sessionState.conf).apply(inputPlan) | ||
assert(outputPlan.find { | ||
case ShuffleExchangeExec(_: HashPartitioning, _, _) => true | ||
case _ => false}.isEmpty, |
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.
ditto
shall we add an end-to-end test for |
|
Change-Id: I0b55a61e1a9ac3555177322ac44d2b216d45bd24
Test build #115630 has finished for PR 26946 at commit
|
case (ShuffleExchangeExec(partitioning, child, _), distribution: OrderedDistribution) => | ||
ShuffleExchangeExec(distribution.createPartitioning(partitioning.numPartitions), child) |
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.
This considers a special case for OrderedDistribution. Generally, if ShuffleExchangeExec is followed by any unsatisfying distribution , we should always trim the ShuffleExchangeExec and apply the partitioning of distribution. Don't we?
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.
Sound reasonable. Any suitable cases?
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.
I just tried few possible cases, but can not have a concrete case like this. Maybe this is the only case possibly. So I think this should be fine.
We can add an end-to-end test, check the physical plan of a query, and count shuffles. |
Sure,I will add some tests for these cases. |
// Range has range partitioning in its output now. To have a range shuffle, we | ||
// need to run a repartition first. | ||
val data = spark.range(0, n, 1, 1).repartition(10).sort($"id".desc) | ||
// Range has range partitioning in its output now. |
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.
shall we remove this comment now? it's not useful as we do add shuffle, the range output partitioning doesn't matter.
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.
okey
@@ -55,12 +54,12 @@ class ConfigBehaviorSuite extends QueryTest with SharedSparkSession { | |||
|
|||
withSQLConf(SQLConf.SHUFFLE_PARTITIONS.key -> numPartitions.toString) { | |||
// The default chi-sq value should be low | |||
assert(computeChiSquareTest() < 100) | |||
assert(computeChiSquareTest() < 10) |
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.
the physical plan is same as before, what caused this change?
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.
They are not same, we had two shuffles before, one was RoundRobinPartitioning, the other was RangePartitioning.
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.
ah i see
sql/core/src/test/scala/org/apache/spark/sql/execution/PlannerSuite.scala
Show resolved
Hide resolved
Test build #115689 has finished for PR 26946 at commit
|
retest this please |
@@ -421,6 +421,52 @@ class PlannerSuite extends SharedSparkSession { | |||
} | |||
} | |||
|
|||
test("SPARK-30036: Romove unnecessary RoundRobinPartitioning " + |
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.
nit Romove
-> Remove
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.
done
Change-Id: I175b3824ba9ce46fba0ebba6ebf0b220d64de42c
Looks fine to me |
Test build #115719 has finished for PR 26946 at commit
|
retest this please |
Test build #115718 has finished for PR 26946 at commit
|
Test build #115729 has finished for PR 26946 at commit
|
retest this please |
Test build #115766 has finished for PR 26946 at commit
|
Merged to master, I guess :-). |
yea merged to master! |
Wait, another point.
And then there is a little difference between The last, if end user really want result partition is 10, should use |
for join, it doesn't require This PR only affects sort. |
df.sort("id").repartition(10) returns wrong result. Global sort result would be repartitioned with disordered. |
Yes it is. But it is similar with outer join. |
Sorry for the wrong example. I mean user should use the right way to change partition. Obviously |
Thanks for pay attention on this. The main problem you described is whether we should change partition num for OrderedDistribution. Correct me if I'm wrong. Thanks |
I see you want to make a way that change partition easily after sort. Only one thing I not sure. If I don not know how committer think about it, or it's just fine. |
what It's more efficient to shuffle only once for query For |
Think we should revert this PR. The change in test |
After more thoughts, I think it's wrong to use optimization to fix a bug. Looking into the bug, the issue is: the I think #27096 is in the right way to optimize redundant shuffles, but we still need to fix the bug about how to handle hints in the parser. I'm reverting this. Let's fix the bug in the parser. |
### Why are the changes needed? `EnsureRequirements` adds `ShuffleExchangeExec` (RangePartitioning) after Sort if `RoundRobinPartitioning` behinds it. This will cause 2 shuffles, and the number of partitions in the final stage is not the number specified by `RoundRobinPartitioning. **Example SQL** ``` SELECT /*+ REPARTITION(5) */ * FROM test ORDER BY a ``` **BEFORE** ``` == Physical Plan == *(1) Sort [a#0 ASC NULLS FIRST], true, 0 +- Exchange rangepartitioning(a#0 ASC NULLS FIRST, 200), true, [id=apache#11] +- Exchange RoundRobinPartitioning(5), false, [id=apache#9] +- Scan hive default.test [a#0, b#1], HiveTableRelation `default`.`test`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#0, b#1] ``` **AFTER** ``` == Physical Plan == *(1) Sort [a#0 ASC NULLS FIRST], true, 0 +- Exchange rangepartitioning(a#0 ASC NULLS FIRST, 5), true, [id=apache#11] +- Scan hive default.test [a#0, b#1], HiveTableRelation `default`.`test`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#0, b#1] ``` ### Does this PR introduce any user-facing change? No ### How was this patch tested? Run suite Tests and add new test for this. Closes apache#26946 from stczwd/RoundRobinPartitioning. Lead-authored-by: lijunqing <lijunqing@baidu.com> Co-authored-by: stczwd <qcsd2011@163.com> Signed-off-by: Wenchen Fan <wenchen@databricks.com>
Why are the changes needed?
EnsureRequirements
addsShuffleExchangeExec
(RangePartitioning) after Sort ifRoundRobinPartitioning
behinds it. This will cause 2 shuffles, and the number of partitions in the final stage is not the number specified by `RoundRobinPartitioning.Example SQL
BEFORE
AFTER
Does this PR introduce any user-facing change?
No
How was this patch tested?
Run suite Tests and add new test for this.