Keyset pagination significantly outperforms offset pagination on large datasets by using the last record's ID as an anchor to fetch subsequent records without scanning all preceding records, achieving approximately 8ms compared to 57ms in a 3-million-record database test, though it requires additional queries to retrieve the last ID for page navigation.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Keyset vs offset pagination in EF Core: 8ms vs 57ms
Added:Your pagination is slow and as your data set grows, it's only going to get worse.
Let's fix it with key set pagination and stay tuned to the end of the video where we'll show you how much quicker key set pagination can be.
With key set pagination, you get the last record in the data set and append it to the query string. The advantage with this is that it will take the next records based on the ID. So, it doesn't have to scan all the records before it.
To write the query, the first thing you need to do is to query the last ID record. This is because you'll need the properties to do the filtering. So, the way that you do that is you await the query. So, we stored it in a separate variable up here which queries the products table. And the reason why we've done that is that we'll need it for later.
So, we query that based on last ID. And then we select the properties that we need and add them into a DTO.
So, we create a new product DTO and the properties that we'll need is the ID, the name. We'll also need the price and we'll also need the category name.
And then we only want the first record.
So, we call first or default a sync and pass in the cancellation token. Now, you could add this into the query string and that would save you an extra query. So, that's another option.
Now, we only want to do the pagination filter if the anchor can be found. If it can't be found, we'll throw an exception.
If it can be found, we can then apply the key set filter.
So, we've created a separate method for that. And we're going to pass in the query, the sort by, the sort direction, and the anchor.
We'll show you how to set up the apply key set filter next.
Watching YouTube tutorials are fine, but if you really want to get familiar with Entity Framework Core, you really need to use it in a real-world application, and that's where my minimal API course comes in.
We use Entity Framework Core throughout to build a real web API from scratch.
Check out the link in the description for more details. Let's now apply the key set filter.
If we're ordering the products by product name in ascending order, the way that we filter is we call the query, and we specify where the name in the product, and we compare it to the anchor name. If that is bigger than zero, then we return the record set.
Now, there is a situation where two product names can be the same or even more. So, we need to combat that. If the product name is equal to the anchor name, and the ID is bigger than the anchor ID.
Now, to do it in descending order, it's very similar, so we can copy and paste that, and we change it from greater than to less than for each of these queries.
Now, if you have multiple sort by options, you'll need to set one up for ascending and descending. So, we've done it here for the price, and it's very similar, but because the price is a decimal, you can just use the greater than and less than sign.
We've also set one up for the category name, but if you've got multiple sort by options, then this is going to get very big.
The final part is to apply the ordering to the query.
We need to set up an order by based on each of the sort by options. So, for the example with the product in ascending order, we order by the product name, and then we've also got that secondary ordering just in case the product name is the same in two records. So, if that's the case, we then order by the product ID.
We've also done it for each of the sort by options in ascending and descending order.
The next step is to run the query and see what SQL it outputs. And if you're getting value from this content, hit the subscribe button as we're going to be doing many more videos on Entity Framework.
And this is an example of the SQL that it outputs.
So, all the pagination filtering happens in the where clause. So, we're saying where the name is bigger than the anchor name or the name is equal to the anchor name and the ID is bigger than the anchor ID just in case the name is the same on more than one record. Bear this in mind because next we're going to show you offset pagination and it outputs the SQL differently.
Offset pagination allows you to skip a number of records and then get a paginated result set from that.
Now, this can cause performance issues, particularly if you've got a large data set. The reason being is that it needs to read all the records before getting your paginated result set.
But, it's a lot more simple to write.
So, with the key set filtering, if you remember, we had to get the anchor and then we had to apply the filtering based on that anchor record.
But, with offset pagination, we don't have to do that. We just get the products and we can still call the apply order that we used with the key set pagination, but all we need to do additionally is just to skip the number of records. We then take the records that we want, select the products, and then return it as part of the response.
And this is an example of the sequel that it outputs. Now, the key differences is that there's no where clause. Instead, there's this offset line where we offset a number of rows, and then we fetch the next rows depending on the size of our pagination.
And it's that line that slows down the performance with offset pagination.
Shortly, we'll show you a speed comparison between keyset and offset pagination. But, to get the full benefits of keyset pagination, we must add indexes.
The products data set has 3 million records, and we haven't added any indexes to it.
Now, we're going to get the keyset pagination and return 500 results. When we do that, it takes over a second to run.
And it's a similar story with the offset pagination. When we run that, it also takes over a second.
Now, this is running on my local machine where the database and the application are on the same machine. You imagine if your database is located elsewhere, you'd also have to add latency time to that response time.
We'll want to add an index for each of the columns that we're filtering at the same time.
So, we're filtering on the ID and the name. We're also filtering on the price and the ID. So, we want to create separate indexes for each of these.
So, in this migration, we've created indexes for the product name and also for the price, including the ID in each of them.
Now, because we're also filtering by category name, we can't do that on the products, but we can create a separate index for the category name.
The moment of truth. The indexes have been applied to the database. We're going to do it from page 100 with a page size of 500. So, with the offset pagination, it's gone down to 57 milliseconds. We do it a few more times.
It's around the 50 to 60 milliseconds mark. Let's compare it with the keyset pagination and see if it's any quicker.
So, we've worked out the last ID for it, and it's 9 milliseconds. So much quicker. 8 milliseconds. Still one more time. 8 milliseconds. So, that's how much quicker keyset pagination can be.
But, to get the last ID in the keyset pagination, we actually have to go to the offset pagination and run page 99 and get the last record from it, so we could perform that query.
And that's one of the disadvantages if you're showing page numbers. You can't really do that unless you've got the last ID. So, you need a way of storing that somehow.
But, if you don't need that and you have a large data set, then keyset pagination might be the way to go. Just as long as your sort by logic isn't too complex.
However, that might not be the reason why your queries are slow. In this video, I look at five different reasons and how you can fix slow queries. So, I'll see you over there.
Related Videos

TOP 15 Data compression Interview Questions and Answers 2019 Part-2 | Data compression | Wisdom jobs
wisdomjobs
281 views•2019-06-28

CTS 158: 802.11w Management Frame Protection
ClearToSend
4K views•2019-02-04

NDSS 2019 Send Hardest Problems My Way: Probabilistic Path Prioritization for Hybrid Fuzzing
NDSSSymposium
496 views•2019-04-02

How realistic is Cities: Skylines?
CityBeautiful
159K views•2019-02-14

GUIs & TUIs: Choosing a User Interface for Your Python Project | Real Python Podcast
realpython
2K views•2025-04-04

The OSI Model - Explained by Example
hnasr
225K views•2019-05-12

Cloud Computing - Introduction
elithecomputerguy
98K views•2019-10-07

From Traveler's Dilemma to Dynamic Routing | Demystifying Networking
IITBombayJuly
5K views•2019-08-04
Trending

WOW! Judge TURNS THE TABLES on Trump in His OWN $10B LAWSUIT!!!
MeidasTouch
197K views•2026-07-23

Playstation NO DISC/NO BUY Fight Is Over...
DavidJaffeGames
4K views•2026-07-23

Steam and Xbox Just Dropped The Hammer On PlayStation
OhNoItsAlexx
9K views•2026-07-23

Americans Confused in Australia for 17 Minutes Straight
IWrocker
17K views•2026-07-23