Skip to content
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

Query: Lift more subqueries in the QueryOptimizer #7822

Closed
wants to merge 1 commit into from

Conversation

tuespetre
Copy link
Contributor

Query models following a simple pattern of selecting from a subquery
only to create a projection can often be flattened by lifting the
subquery. These changes do that, which results in more efficient
queries for such cases, and in the case of Relational, more compact
SQL statements.

@dnfclas
Copy link

dnfclas commented Mar 9, 2017

@tuespetre,
Thanks for having already signed the Contribution License Agreement. Your agreement was validated by .NET Foundation. We will now review your pull request.
Thanks,
.NET Foundation Pull Request Bot

@@ -76,6 +76,8 @@ public QueryOptimizer([NotNull] IModel model)
_queryAnnotations = queryAnnotations;

VisitQueryModel(queryModel);

new MainFromClauseFlatteningQueryModelVisitor(queryAnnotations).VisitQueryModel(queryModel);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about overriding VisitMainFromClause here?

Copy link
Contributor Author

@tuespetre tuespetre Mar 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't work, the SubQueryFlattener base class will not hit all of the SubQueryExpressions and it won't hit the MainFromClause unless its own conditions are met (no result operators, etc.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can always override VisitMainFromClause apply your logic and if it doesn't work then call base. Question becomes if we want to do this merging in MainFromClause only or on AdditionalFromClause too (later may be better but probably needs some more tests to be added).
We are already overriding FlattenSubquery there you should be getting all subquery expressions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smitpatel that is what I tried first. It doesn't get all of the subquery expressions, and the SubQueryFromClauseFlattener base class won't even visit the MainFromClause if there are result operators on the query model.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tuespetre - You are right. It does not get all subquery expressions. The dual dilemma of ExpressionVisitor & QueryModelVisitor (which forces @maumar to make recursive visitors)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are using Expression/QueryModelVisitor pattern, can you move visiter creation & entry calls to EntityQueryModelVisitor.OptimizeQueryModel method. QueryOptimizer is a visitor on query model. So it is a stand-alone thing. If we need any other visitor on QMV then we add visitor in optimize query model just like SubQueryMemberPushDown or EntityEqualityRewriting.

Rest of changes look good to accommodate it. Its really unfortunate that QueryOptimizer is suboptimal at present to deal with such cases.

@tuespetre tuespetre force-pushed the query-optimizer branch 2 times, most recently from f405bab to 4cd141d Compare March 10, 2017 14:25
Query models following a simple pattern of selecting from a subquery
only to create a projection can often be flattened by lifting the
subquery. These changes do that, which results in more efficient
queries for such cases, and in the case of Relational, more compact
SQL statements.
@tuespetre
Copy link
Contributor Author

🆙📅


if (querySourceReferenceExpression != null
&& querySourceReferenceExpression.ReferencedQuerySource == groupJoinClause)
if (queryModel.BodyClauses.ElementAtOrDefault(index + 1) is AdditionalFromClause additionalFromClause
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a side note: can we avoid having such cleanups in the PRs which fixes certain bugs/issues? It makes harder to review when finding what code path actually changed. We generally run clean up on whole code together so that we don't have to review it in detail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want me to cut this part?

@tuespetre
Copy link
Contributor Author

@smitpatel which test is regressing that you had mentioned on #6647?

@smitpatel
Copy link
Contributor

This PR is superseded by #7843
@tuespetre - QueryOptimizer is good place to capture optimizations on QueryModel which are based on structure of QM. We wanted to include this change in QueryOptimizer but it was regressing a test as pointed out in #7844 . After investigating it, considering the cause of the issue may not be us, we decided that we are fine with that test change.

@smitpatel smitpatel closed this Mar 10, 2017
@tuespetre
Copy link
Contributor Author

OK. There are still cases that the SubQueryFromClauseFlattener will never hit, though (Contains_with_subquery_optional_navigation_and_constant_item).

@smitpatel
Copy link
Contributor

Thanks for pointing out. I will investigate into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants