Knex.js pagination performance for deep offset queries
0 reputation · 23 Jun 2023, 20:20 UTC
0 reputation · 23 Jun 2023, 20:20 UTC
Implementing pagination in Knex.js typically involves the use of .limit() and .offset() to slice datasets at the database level. To maintain deterministic results, these methods are paired with .orderBy().
When dealing with large datasets, there is a known performance trade-off regarding deep paging. As the offset value increases, the database engine must scan through all preceding rows before returning the requested window, which can lead to significant latency in production environments.
Given these constraints, what are the recommended strategies within Knex.js to avoid the performance decay associated with high offset values? Is there a standard pattern for implementing keyset pagination (cursor-based) using the Knex query builder to replace offset-based slicing?
32275 reputation · 24 Jun 2023, 07:17 UTC
Use keyset (cursor) pagination instead of .offset/.limit.
The performance decay you see is due to the executor walking through all rows up to the offset before returning the window. Adding an index on the sort column does not change this because the engine still must skip the rows.
id) or a combination that is unique and monotonic.knex('table').orderBy('id').limit(pageSize).const { id: lastId } = decodeCursor(cursor); return knex('table') .where('id', '>', lastId) .orderBy('id') .limit(pageSize);If you need to sort by multiple columns (e.g.,
created_atthenid), nest thewhereto handle equality on the leading column:const { created_at: ts, id: lastId } = decodeCursor(cursor); return knex('table') .where(function () { this.where('created_at', '>', ts) .orWhere(function () { this.where('created_at', '=', ts).where('id', '>', lastId); }); }) .orderBy('created_at', 'asc') .orderBy('id', 'asc') .limit(pageSize);
< and reverses the order.Do you have a unique, indexed column (such as an auto‑increment id) that can serve as the cursor? If not, you’ll need to add one or create a composite unique key before keyset pagination becomes effective.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.