-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fix: optimizer common_sub_expression_eliminate fails in a window function
#17852
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
fix: optimizer common_sub_expression_eliminate fails in a window function
#17852
Conversation
Window::try_new because input schema has changed|
From #17770 (comment) My initial thought was changing datafusion/datafusion/optimizer/src/common_subexpr_eliminate.rs Lines 223 to 227 in 297e537
This change worked: The generated plan: |
|
I tried to return early here if there is no common node: datafusion/datafusion/optimizer/src/common_subexpr_eliminate.rs Lines 172 to 174 in 297e537
However, the optimizer failed in 'optimize_projections': If I disable the entire diff --git a/datafusion/optimizer/src/optimizer.rs b/datafusion/optimizer/src/optimizer.rs
index 084152d40..ca4a85692 100644
--- a/datafusion/optimizer/src/optimizer.rs
+++ b/datafusion/optimizer/src/optimizer.rs
@@ -252,7 +252,7 @@ impl Optimizer {
// The previous optimizations added expressions and projections,
// that might benefit from the following rules
Arc::new(EliminateGroupByConstant::new()),
- Arc::new(CommonSubexprEliminate::new()),
+ // Arc::new(CommonSubexprEliminate::new()),
Arc::new(OptimizeProjections::new()),
];In fact, the same issue happens if I disable everything in between diff --git a/datafusion/optimizer/src/optimizer.rs b/datafusion/optimizer/src/optimizer.rs
index 084152d40..684b01b88 100644
--- a/datafusion/optimizer/src/optimizer.rs
+++ b/datafusion/optimizer/src/optimizer.rs
@@ -234,25 +234,25 @@ impl Optimizer {
Arc::new(EliminateJoin::new()),
Arc::new(DecorrelatePredicateSubquery::new()),
Arc::new(ScalarSubqueryToJoin::new()),
- Arc::new(DecorrelateLateralJoin::new()),
- Arc::new(ExtractEquijoinPredicate::new()),
- Arc::new(EliminateDuplicatedExpr::new()),
- Arc::new(EliminateFilter::new()),
- Arc::new(EliminateCrossJoin::new()),
- Arc::new(EliminateLimit::new()),
- Arc::new(PropagateEmptyRelation::new()),
- // Must be after PropagateEmptyRelation
- Arc::new(EliminateOneUnion::new()),
- Arc::new(FilterNullJoinKeys::default()),
- Arc::new(EliminateOuterJoin::new()),
- // Filters can't be pushed down past Limits, we should do PushDownFilter after PushDownLimit
- Arc::new(PushDownLimit::new()),
- Arc::new(PushDownFilter::new()),
- Arc::new(SingleDistinctToGroupBy::new()),
- // The previous optimizations added expressions and projections,
- // that might benefit from the following rules
- Arc::new(EliminateGroupByConstant::new()),
- Arc::new(CommonSubexprEliminate::new()),
+ // Arc::new(DecorrelateLateralJoin::new()),
+ // Arc::new(ExtractEquijoinPredicate::new()),
+ // Arc::new(EliminateDuplicatedExpr::new()),
+ // Arc::new(EliminateFilter::new()),
+ // Arc::new(EliminateCrossJoin::new()),
+ // Arc::new(EliminateLimit::new()),
+ // Arc::new(PropagateEmptyRelation::new()),
+ // // Must be after PropagateEmptyRelation
+ // Arc::new(EliminateOneUnion::new()),
+ // Arc::new(FilterNullJoinKeys::default()),
+ // Arc::new(EliminateOuterJoin::new()),
+ // // Filters can't be pushed down past Limits, we should do PushDownFilter after PushDownLimit
+ // Arc::new(PushDownLimit::new()),
+ // Arc::new(PushDownFilter::new()),
+ // Arc::new(SingleDistinctToGroupBy::new()),
+ // // The previous optimizations added expressions and projections,
+ // // that might benefit from the following rules
+ // Arc::new(EliminateGroupByConstant::new()),
+ // Arc::new(CommonSubexprEliminate::new()),
Arc::new(OptimizeProjections::new()),
];
|
c15a4f6 to
172de54
Compare
172de54 to
86efa98
Compare
common_sub_expression_eliminate fails in a window function
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.
Makes sense to me, thanks for the detailed breakdown in the issue & this PR to help me understand the root cause and fix 👍
I think we should add the original query that highlighted this bug to the test suite, perhaps in the window SLT. Also would be nice if could place a code comment right above that project to explain it (we do have that docstring comment on ScalarSubqueryToJoin struct but it's a bit far removed from the code fix so might be hard to link them together). Perhaps something like:
// Preserve original schema as new Join might have more fields than what Filter & parents expectSomewhat unrelated thoughts
It does make me wonder why we have this invariant, on Window nodes that requires this schema matching; it feels like a bit of a limitation, but I guess that's what Window::try_new is supposed to fix but apparently isn't as performant. It would be nice if we could uplift the Window::try_new_with_schema function with some documentation explaining when to use it, etc. Especially as the original error message (Window has mismatch between number of expressions (1) and number of fields in schema (0)) is not very descriptive. I'll raise a separate issue for this.
Edit: raised #17912
|
Thank @Jefffrey I added the tests to |
Oh that's weird, maybe something in the configs used for SLT 🤔 It would be nice to have an explicit test for this somewhere, I'll try look at SLT a bit to see why this might be happening |
|
Oh I think it's this: datafusion/datafusion/sqllogictest/test_files/window.slt Lines 2591 to 2605 in daeb659
We never set it back to false so I guess the test at the bottom of the file was affected; a bit concerning we have these set configs across our SLTs but not much guarantee that the tests they were added for will clean them up. Perhaps try putting this before the test: Edit: or better yet, fix that above snippet to set back to false for the second set (I assume that was the intention) |
|
Thanks. I disable the rule and the test failed without the change: |
|
Raised #17914 btw just for tracking (don't know if this is happening in other SLT files, but I assume so) |
Which issue does this PR close?
Rationale for this change
The optimizer fails on this query:
#17770 (comment):
scalar_subquery_to_joinrewrites the input schema fed to the window function, creating an invalid plan.What changes are included in this PR?
In
ScalarSubqueryToJoin, add a projection on top of the filter after converting the subquery to a join, similar toEliminateGroupByConstant:datafusion/datafusion/optimizer/src/eliminate_group_by_constant.rs
Lines 26 to 30 in 10a437b
Are these changes tested?
Yes, using the existing test suite.
I verified using the query noted in the issue:
Are there any user-facing changes?
No.