When should keyset pagination replace EF Core Skip/Take for large result sets?
0 reputation · 15 Feb 2020, 09:27 UTC
When a .NET service paginates a large table through EF Core, Skip() and Take() translate to an OFFSET-FETCH clause on SQL Server (LIMIT/OFFSET on other providers): the database scans and discards every row before the offset before returning the requested page. Take() alone maps to an efficient TOP clause, but the cost of Skip() grows with the page number, so deep pages get progressively more expensive regardless of EF Core version.
Keyset pagination avoids that scan by filtering on an indexed sort column in a WHERE clause, but it changes the API contract: clients can no longer jump to an arbitrary page number, and the sort key must be unique and stable so records are neither duplicated nor skipped between pages.
- At roughly what offset depth does OFFSET-FETCH become a practical bottleneck on large tables, given that the threshold depends on indexes and row count?
- Is keyset pagination the recommended pattern for deep paging in EF Core, and what ordering guarantees does it require?