SQL

Anti-pattern : OFFSET profond — passer au keyset

OFFSET 20000 lit et jette 20 000 lignes à chaque page. La pagination keyset (seek) repart du dernier élément vu : coût constant quelle que soit la profondeur.

Cas d'usage

Pagination d'API ou de back-office sur des tables volumineuses, scroll infini.

Prérequis

Index sur les colonnes de tri (created_at DESC, id DESC)

SQL
-- Anti-pattern : la page 1000 lit 20 020 lignes pour en garder 20
SELECT * FROM products
ORDER BY created_at DESC, id DESC
LIMIT 20 OFFSET 20000;

-- Correctif : keyset — on repart du dernier élément de la page précédente
SELECT * FROM products
WHERE (created_at, id) < ('2026-06-01 12:34:56', 18432)
ORDER BY created_at DESC, id DESC
LIMIT 20;
-- Le tuple (created_at, id) garantit un ordre total même à timestamp égal

Résultat

  id   |     created_at      |   name
-------+---------------------+-----------
 18431 | 2026-06-01 12:31:08 | Produit A
 18419 | 2026-06-01 12:18:55 | Produit B
 18402 | 2026-06-01 11:59:02 | Produit C
(20 rows)

-- OFFSET 20000 : Execution Time: 412.480 ms (lit 20 020 lignes)
-- Keyset       : Execution Time:   0.524 ms (lit 20 lignes)
SQLPaginationKeysetPerformance

Snippets liés

Retour au Data Lab