Кейс: OFFSET 100000 положил время ответа API
Пагинация каталога делалась стандартно: SELECT ... OFFSET :offset LIMIT 20. На первых страницах всё летало, на выдаче за offset больше пятидесяти тысяч ответ рос до нескольких секунд.
Причина в том, как Postgres выполняет OFFSET: движок обязан просканировать и отбросить все offset строк перед тем, как отдать limit. При offset 100000 это буквально сто тысяч прочитанных и выброшенных строк на каждый запрос — независимо от того, что вернуть нужно всего двадцать.
Решение — keyset pagination: вместо смещения передавать курсор в виде id последней увиденной строки и двигаться по индексу вперёд.
SELECT id, name, price FROM products WHERE id > :lastId ORDER BY id LIMIT 20;
Запрос с WHERE id > :lastId использует индекс по id напрямую и не сканирует лишние строки — сложность не зависит от глубины страницы.
Что спросят следом: как обеспечить стабильную сортировку, если ключевая колонка не уникальна. Ответ — добавить уникальный tie-breaker в ORDER BY, например (created_at, id), иначе при одинаковых значениях сортировки строки могут повторяться или пропадать между страницами.
Глубина страницы не должна влиять на время ответа — если влияет, это сигнал, что используется OFFSET там, где нужен курсор.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки