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: optimize binary expression AndAlso and OrElse where left and right are the same #18525

Closed
maumar opened this issue Oct 23, 2019 · 1 comment · Fixed by #18694
Closed
Assignees
Milestone

Comments

@maumar
Copy link
Contributor

maumar commented Oct 23, 2019

Sometimes after running optimizations we end up with expressions like:

(c.Property IS NULL AND c.Property IS NULL) OR (c.Property2 IS NOT NULL AND c.Property2 IS NOT NULL)

this can be optimized to:

c.Property IS NULL OR c.Property2 IS NOT NULL

moreover, case like:

c.Property IS NULL OR c.Property IS NOT NULL

is tautology, which we can also recognize (similarly for AND, resolving to always being false

@maumar
Copy link
Contributor Author

maumar commented Oct 23, 2019

example test: Where_concat_string_int_comparison4

@ajcvickers ajcvickers added this to the 3.1.0 milestone Oct 23, 2019
maumar added a commit that referenced this issue Nov 1, 2019
Resolves #17543 - Queries really slow due to null checks
Resolves #18525 - Query: optimize binary expression AndAlso and OrElse where left and right are the same
Resolves #18547 - DbFunctions compared to NULL are ignored and break the query builder

#17543

Before when rewriting null comparisons we would always remove possibility of nulls in the resulting expression. This is not always needed, specifically in predicates, where it doesn't really matter if expression returns false or null - the result is the same.
Now we detect those cases and apply "simplified" null expansion which should lead to better performance.

#18525

Null semantics initially expands expressions to a verbose form which then gets simplified in query optimizer. One of the optimizations added is when we do AND/OR where both sides are the same. Other small improvements have been added in this change also.

#18525

Previously we assumed that function can only be null if at least one of its arguments is null. This is the case for most built-in functions, but not all. This also goes for user defined functions which can return arbitrary results.
Fix is to treat all functions as potentially nullable. This leads to worse queries is some cases, but is also mitigated by other improvements added along side.
In the future we will provide metadata to better determine given function's nullability.

Also fixed a few small bug found along the way - incorrect Equals comparison for SqlExpression, for cases when TypeMapping was null.
maumar added a commit that referenced this issue Nov 1, 2019
Resolves #17543 - Queries really slow due to null checks
Resolves #18525 - Query: optimize binary expression AndAlso and OrElse where left and right are the same
Resolves #18547 - DbFunctions compared to NULL are ignored and break the query builder

#17543

Before when rewriting null comparisons we would always remove possibility of nulls in the resulting expression. This is not always needed, specifically in predicates, where it doesn't really matter if expression returns false or null - the result is the same.
Now we detect those cases and apply "simplified" null expansion which should lead to better performance.

#18525

Null semantics initially expands expressions to a verbose form which then gets simplified in query optimizer. One of the optimizations added is when we do AND/OR where both sides are the same. Other small improvements have been added in this change also.

#18525

Previously we assumed that function can only be null if at least one of its arguments is null. This is the case for most built-in functions, but not all. This also goes for user defined functions which can return arbitrary results.
Fix is to treat all functions as potentially nullable. This leads to worse queries is some cases, but is also mitigated by other improvements added along side.
In the future we will provide metadata to better determine given function's nullability.

Also fixed a few small bug found along the way - incorrect Equals comparison for SqlExpression, for cases when TypeMapping was null.

Additional refactoring:
- removed the second pass of sql optimizations (we do it later when sniffing parameter values anyway)
- consolidated NullComparisonTransformingExpressionVisitor into SqlExpressionOptimizingExpressionVisitor
maumar added a commit that referenced this issue Nov 1, 2019
Resolves #17543 - Queries really slow due to null checks
Resolves #18525 - Query: optimize binary expression AndAlso and OrElse where left and right are the same
Resolves #18547 - DbFunctions compared to NULL are ignored and break the query builder

#17543

Before when rewriting null comparisons we would always remove possibility of nulls in the resulting expression. This is not always needed, specifically in predicates, where it doesn't really matter if expression returns false or null - the result is the same.
Now we detect those cases and apply "simplified" null expansion which should lead to better performance.

#18525

Null semantics initially expands expressions to a verbose form which then gets simplified in query optimizer. One of the optimizations added is when we do AND/OR where both sides are the same. Other small improvements have been added in this change also.

#18547

Previously we assumed that function can only be null if at least one of its arguments is null. This is the case for most built-in functions, but not all. This also goes for user defined functions which can return arbitrary results.
Fix is to treat all functions as potentially nullable. This leads to worse queries is some cases, but is also mitigated by other improvements added along side.
In the future we will provide metadata to better determine given function's nullability.

Also fixed a few small bug found along the way - incorrect Equals comparison for SqlExpression, for cases when TypeMapping was null.

Additional refactoring:
- removed the second pass of sql optimizations (we do it later when sniffing parameter values anyway)
- consolidated NullComparisonTransformingExpressionVisitor into SqlExpressionOptimizingExpressionVisitor
@maumar maumar closed this as completed in dd92ba3 Nov 2, 2019
@ajcvickers ajcvickers modified the milestones: 3.1.0-preview3, 3.1.0 Dec 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants