Optimize DISTINCT over singleton collections#34702
Conversation
| throw new InvalidOperationException(RelationalStrings.DistinctOnCollectionNotSupported); | ||
| } | ||
|
|
||
| if (Limit is SqlConstantExpression { Value: 0 or 1 }) |
There was a problem hiding this comment.
does it make sense to handle the case of 0? AFAICT SELECT expressions with a LIMIT 0 could be optimized away heavily (basically only the projection/typing matters; offset, predicate, distinct, ... are all irrelevant)
There was a problem hiding this comment.
Yeah, I agree - if we want to optimize the LIMIT 0 case, we should probably do that separately and go much farther than just removing DISTINCT... Any thoughts on cases where LIMIT 0 could be an actually useful thing to do (and therefore worth working on)?
There was a problem hiding this comment.
A corner case where a LIMIT of 0 is sometimes used (that I know of) is in paginated queries that (ab?)use it to only retrieve the count of the relevant entities, but that is usually going to be handled as a 0-valued parameter.
| } | ||
|
|
||
| Limit = sqlExpression; | ||
| if (Offset is null && Limit is SqlConstantExpression { Value: 0 or 1 }) |
There was a problem hiding this comment.
nit:
| if (Offset is null && Limit is SqlConstantExpression { Value: 0 or 1 }) | |
| if (Offset is null && Limit is SqlConstantExpression { Value: 0 or 1 }) |
| throw new InvalidOperationException(RelationalStrings.DistinctOnCollectionNotSupported); | ||
| } | ||
|
|
||
| if (Limit is SqlConstantExpression { Value: 0 or 1 }) |
There was a problem hiding this comment.
Yeah, I agree - if we want to optimize the LIMIT 0 case, we should probably do that separately and go much farther than just removing DISTINCT... Any thoughts on cases where LIMIT 0 could be an actually useful thing to do (and therefore worth working on)?
2edd5b9 to
41482f6
Compare
41482f6 to
a592e72
Compare
|
I dropped the limit=0 cases; if optimizations are desired for them, they can be way more aggressive and best handled separately (as they basically drop any rows). |
This does some progress towards fixing #34482, but in several cases the optimization does not trigger because of another intermediate operation.
I will investigate whether it makes sense to combine these operations in a separate PR or if they can be easily handled in this one.
The
Single/First[OrDefault]case seems to be reasonably tested; for theTake(1)case it might be better to add a new test (it is tested, but AFAICT only in combination withSingle/First[OrDefault]).