Uh oh!
There was an error while loading. Please reload this page.
[SPARK-12978][SQL] Skip unnecessary final group-by when input data already clustered with group-by keys - #10896
[SPARK-12978][SQL] Skip unnecessary final group-by when input data already clustered with group-by keys#10896maropu wants to merge 21 commits into
Conversation
SparkQA
commented
Jan 25, 2016
Test build #49985 has finished for PR 10896 at commit
|
SparkQA
commented
Jan 25, 2016
Test build #49988 has finished for PR 10896 at commit
|
maropu
commented
Feb 2, 2016
@marmbrus Could you review this and give me suggestions? |
marmbrus
commented
Feb 2, 2016
@yhuai would be better to review this, but neither of those plans look great to me. Why are we not partial aggregating before a shuffle? Seems like that will ship a lot of data around for no reason. |
yhuai
commented
Feb 3, 2016
I guess that exchange is added because there is a |
maropu
commented
Feb 3, 2016
Yes, it is. The input query is; |
marmbrus
commented
Feb 3, 2016
Okay, but that code doesn't actually produce an exchange right? Since its captured by the cache? Eitherway, I'll let @yhuai sign off on this. |
There was a problem hiding this comment.
I think it would be clearer if you called this partialAggregation. Its not unnecessary, its an optimization in most cases.
maropu
commented
Feb 4, 2016
Ah, yes..., the code produces no exchange because of cache. |
maropu
commented
Feb 4, 2016
As @marmbrus said, we also need push down partial aggregation under an exchange; into |
maropu
commented
Feb 5, 2016
@yhuai ping |
SparkQA
commented
Feb 5, 2016
Test build #50812 has finished for PR 10896 at commit
|
maropu
commented
Feb 9, 2016
@yhuai ping |
yhuai
commented
Feb 10, 2016
I probably will not be able to take a close look on this PR until later this month. I have a question regarding the approach of PR. Right now, we always plan partial aggregation operators first (in SparkStrategies) and then add Exchange operators (in EnsureRequirements). Another approach will be that we do not add partial aggregation operators in SparkStrategies. Then, after we figure out where we need exchange operators, we add partial aggregation operators. This approach probably needs more code changes. But, I feel it is a more cleaner approach. |
maropu
commented
Feb 15, 2016
@yhuai The second approach's good to me though, I'm not exactly sure how to remove unnecessary final aggregation covered in this pr. IMO these kinds of partial aggregation optimization seem to be similar to |
SparkQA
commented
Apr 25, 2016
Test build #56883 has finished for PR 10896 at commit
|
SparkQA
commented
Apr 25, 2016
Test build #56884 has finished for PR 10896 at commit
|
rxin
commented
May 20, 2016
cc @hvanhovell can you review this? |
maropu
commented
May 25, 2016
@hvanhovell ping |
hvanhovell
commented
May 25, 2016
@maropu I'll take a look today. Is the description up-to-date? |
maropu
commented
May 25, 2016
@hvanhovell yeah, it is up-to-dated. |
There was a problem hiding this comment.
Partial aggregation IMO implies that we add a partial aggregation step. What do you think?
There was a problem hiding this comment.
Why not move this code block into aggregate.Utils.planAggregateWithoutDistinct?
maropu
commented
May 31, 2016
Thank for you comments! I'll check them in a few days. |
2b1bea6 to
36553bcCompare| def unapply(plan: SparkPlan): Option[Distribution] = plan match { | ||
| case agg: AggregateExec | ||
| if agg.aggregateExpressions.map(_.aggregateFunction).forall(_.supportsPartial) => |
There was a problem hiding this comment.
Put this in a function. This can be found a few times in the code.
maropu
commented
Aug 24, 2016
okay, done |
SparkQA
commented
Aug 24, 2016
Test build #64322 has finished for PR 10896 at commit
|
SparkQA
commented
Aug 24, 2016
Test build #64324 has finished for PR 10896 at commit
|
SparkQA
commented
Aug 25, 2016
Test build #64388 has finished for PR 10896 at commit
|
maropu
commented
Aug 25, 2016
@hvanhovell could you also give me comments on #13852? |
hvanhovell
commented
Aug 25, 2016
LGTM - merging to master. Thanks! |
After this PR, we create the partial aggregate operator in I have a simpler idea: add a new rule which is run after |
| * If the first aggregation needs a shuffle to satisfy its distribution, a map-side partial | ||
| * an aggregation and a shuffle are added in `EnsureRequirements`. | ||
| */ | ||
| def planStreamingAggregation( |
There was a problem hiding this comment.
have we tested the streaming aggregation with the optimization?
There was a problem hiding this comment.
Yes, it is a bit risky to touch this part.
liancheng
commented
Aug 30, 2016
+1 for @cloud-fan's proposal. Instead of creating a performant plan using tricky code, it's clearer to create a naive but correct physical plan first and then optimize it. |
hvanhovell
commented
Aug 30, 2016
You could also argue the other way around, planning a partial aggregate is also a premature optimization, and that the planning of such an I do think things could be simplified even more, and that either pruning an unneeded partial aggregate or planning one in a new rule both have merit. |
@cloud-fan@liancheng yea, adding a new rule after |
cloud-fan
commented
Aug 30, 2016
I agree that partial aggregate is also kind of optimization, and it's tricky to put it in planner. I think it makes sense to clean it up, after we have sufficient discussion and come to a consensus, but not finishing it within an optimization. For this particular optimization, I think it's much simpler to add an extra rule to merge the partial and final aggregate, than spreading the aggregation stuff to cc @yhuai too |
maropu
commented
Aug 30, 2016
Sorry for my bad explanation. yes, I agree that we remove the aggregation stuff from |
yhuai
commented
Aug 30, 2016
@maropu Thank you for working on this. Sorry that I did not get time to look at it after you updated the pr. I looked at it today. I think this optimization deserves a feature flag since it determines if we can generate a valid physical plan. We can enable it by default. But, we will have the flexibility to disable it when there is an issue. After looking at the code, I am not sure it is a good approach to put the logic of adding partial aggregate operators in EnsureRequirements. Originally, I thought we could have a individual rule to add partial aggregate operators and then either extract logic in EnsureRequirements as a utility function or run EnsureRequirements again. Also, due to the complexity of the logic for planning aggregations, seems after the change it is hard to track the planner logic. So, seems it will be good to try your your original proposal by adding a rule to remove unnecessary operators (like @cloud-fan implemented in #14876). In this way, it will also be very easy to add the feature flag and keep the optimization rule in a single place. Later, we can revisit this approach if we can clean up the planner logic for aggregation. What do you think? |
maropu
commented
Aug 31, 2016
@yhuai Thanks your comment and I agree with you. We'll keep the discussion. |
## What changes were proposed in this pull request? according to the discussion in the original PR #10896 and the new approach PR #14876 , we decided to revert these 2 PRs and go with the new approach. ## How was this patch tested? N/A Author: Wenchen Fan <wenchen@databricks.com> Closes#14909 from cloud-fan/revert.
This ticket targets the optimization to skip an unnecessary group-by operation below;
Without opt.:
With opt.: