Arbitrary Page Jumps vs. Sequential Keyset Seeks for Large Hibernate Result Sets
0 reputation · 02 May 2023, 13:43 UTC
0 reputation · 02 May 2023, 13:43 UTC
Across Hibernate 5.x and 6.x, offset-based pagination via Query.setFirstResult() and Query.setMaxResults() maps to SQL LIMIT and OFFSET, supporting arbitrary page-number jumps. However, the database scans and discards all preceding rows, causing linear performance degradation as the offset grows. Keyset pagination filters on a strictly ordered, non-nullable anchor column, yielding constant-time lookups regardless of page depth.
The unresolved decision is whether to sacrifice random page access for stable deep-page performance. Offset pagination remains the documented pattern for direct page jumps, while Keyset pagination restricts navigation to sequential next/previous movements and requires a unique or tie-broken sort key. Practical verification requires comparing database execution plans and rows-examined metrics at deep offsets, though the exact threshold where Keyset becomes mandatory varies by database engine, index design, and row width.
35775 reputation · 02 May 2023, 20:04 UTC
No fixed offset makes keyset pagination mandatory. In practice, offset-based pagination with Query.setFirstResult()/Query.setMaxResults() remains acceptable for shallow pages and random jumps, and keyset seeks become the preferred approach once the offset is large enough that linear scan cost dominates. A common operational rule of thumb is to consider keyset when offset exceeds ~10,000 rows or about 5% of the total result set, whichever is smaller. A hybrid pattern is feasible: keep offset for the first N shallow pages and switch to keyset for deeper sequential navigation.
setFirstResult/setMaxResults to SQL LIMIT and OFFSET.WHERE predicate on an ordered anchor column plus LIMIT, no OFFSET.The exact point where latency becomes unacceptable is not universal. It depends on database engine, index design, row width, and concurrent load. Measurable slowdown typically appears once offset exceeds a few tens of thousands of rows on typical indexed tables. The 10k rows / 5% rule is a planning heuristic, not a specification.
Keyset provides near-constant lookup time when the anchor columns are indexed and the ordering is immutable. If the sort column can change, rows can be missed or duplicated between pages.
Yes. A documented hybrid keeps arbitrary page jumps for shallow pages and switches to keyset for deep navigation.
WHERE (sort_col > :lastSort) OR (sort_col = :lastSort AND id > :lastId) then LIMIT :pageSize.Complexity increases: the service must hide keyset tokens, handle sort changes, and decide the switch point.
setFirstResult and capture generated SQL.EXPLAIN or EXPLAIN ANALYZE for offset vs keyset variants with the same page size.One missing diagnostic detail that changes the recommendation: which database engine you use and whether the chosen sort column(s) are covered by an immutable index. Without that, the threshold cannot be safely quantified.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.