Query perf: Parameterization of Skip() and Take()
See original GitHub issueParameterization can benefit performance because it increases the chances of cache hits on both EF’s query cache and the database’s query cache.
Currently arguments of Skip()
and Take()
are almost never parameterized (at least in simple queries) because we follow the simple rule that we only parameterize captured variables and Skip()
and Take()
don’t do that.
Note that assuming an application with a fixed page size, variability is expected to be higher on the argument of Skip()
than on the argument of Take()
.
From my recollection solving this in EF6 yielded a performance improvement of more than 10% on micro-benchmarks that executed queries that returned pages of 20 rows.
There are a couple options as far as I can see:
- Add overloads that take
Expression<Func<int>>
toQueryableExtensions
as we did in EF6.- Pros: it solves the problem without breaking our currently simple parameterization rules; the user opts in parameterization and can opt out for the cases in which a constant performs better or if the database doesn’t support it or ; it “fixes” LINQ to honor closure semantics for these operators like it does for most of the other LINQ operators.
- Cons: users needs to know about the existence of the overload to take advantage of it.
- Force parameterization of these operators even when we receive an integer constant.
- Pros: users benefits without knowing how we do it.
- Cons: parameterization on paging may not be compatible with some databases, including older versions of SQL Server, so we might need more knobs to opt in/out (although I suspect this may affect
Take()
- which is often translated to TOP - more thanSkip()
in which case maybe forcing parameterization ofSkip()
only would be a good compromise); we need to figure out how to break our own parameterization rules without breaking anything else 😄; closure semantics will still be broken for paging.
My current preference is that we could do a combination of both, e.g. force parameterization of Skip()
(if we confirm that it is generally harmless for database support) and add the lambda overloads to “fix” LINQ.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:2
- Comments:5 (3 by maintainers)
Top GitHub Comments
@zuckerthoben Can you file a new issue with a runnable project/solution or complete code listing that demonstrates the behavior you are seeing so that we can investigate?
I guess option 2 only works when putting in constant int? I have an API that forwards the skip and take parameters to the client. That way I dont get parameterized queries, without the expression overload known from EF6.
Background is that my Azure database is recommending “Parameterized Queries” and I don’t see a way to fix this in my search action that uses EF Core. I am inclined to rewrite the search action with ADO.NET to fix the performance issue. Any ideads on my case?