-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Additional perf improvements around null semantics scenarios #18694
Conversation
cc: @ajcvickers @Pilchie |
@@ -275,7 +275,7 @@ public override async Task String_starts_with_on_argument_with_wildcard_column_n | |||
@"SELECT [f].[FirstName] AS [fn], [f0].[LastName] AS [ln] | |||
FROM [FunkyCustomers] AS [f] | |||
CROSS JOIN [FunkyCustomers] AS [f0] | |||
WHERE (([f0].[LastName] <> N'') OR [f0].[LastName] IS NULL) AND ([f].[FirstName] IS NOT NULL AND ([f0].[LastName] IS NOT NULL AND (LEFT([f].[FirstName], LEN([f0].[LastName])) <> [f0].[LastName])))"); | |||
WHERE (([f0].[LastName] <> N'') OR [f0].[LastName] IS NULL) AND ([f].[FirstName] IS NOT NULL AND ([f0].[LastName] IS NOT NULL AND ((LEFT([f].[FirstName], LEN([f0].[LastName])) <> [f0].[LastName]) OR LEFT([f].[FirstName], LEN([f0].[LastName])) IS NULL)))"); |
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.
Commit message has wrong issue reference. |
src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs
Show resolved
Hide resolved
@smitpatel new version up |
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
src/EFCore.Relational/Query/Internal/NullSemanticsRewritingExpressionVisitor.cs
Show resolved
Hide resolved
{ | ||
_canOptimize = testIsCondition; | ||
var newTest = (SqlExpression)Visit(whenClause.Test); | ||
_canOptimize = false; |
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.
There's no need to keep setting it to false. There's no code that could set it to true
@@ -32,7 +32,8 @@ public override bool Equals(object obj) | |||
|
|||
private bool Equals(SqlExpression sqlExpression) | |||
=> Type == sqlExpression.Type | |||
&& TypeMapping?.Equals(sqlExpression.TypeMapping) == true; | |||
&& ((TypeMapping == null && sqlExpression.TypeMapping == null) | |||
|| TypeMapping?.Equals(sqlExpression.TypeMapping) == 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.
Equals(TypeMapping, sqlExpression.TypeMapping)
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.