Offset медленный на глубине и ломается при изменении данных; cursor стабилен и O(1) через index seek, но без jump на «страницу 47».
Разбор
Почему offset медленный. OFFSET 100000 LIMIT 20 заставляет БД сгенерировать и выбросить 100 000 строк. Стоимость растёт линейно с offset — deep pages всё медленнее.
Почему cursor быстрый. WHERE id < 8423 ORDER BY id DESC LIMIT 20 — seek по index на id, чтение 20 строк. Страница 1 и 50 000 стоят одинаково.
Correctness bug offset. На page 1 вставили элемент сверху — OFFSET 20 для page 2 вернёт уже виденный — duplicates. Удаления — skips. На живом списке offset врёт. Cursor якорится на значение строки — top-insert не сдвигает boundary.
Что такое cursor. Opaque token — sort key последней строки, base64: base64({ id: 8423, created_at: "..." }). Сортировка по non-unique (created_at) — нужен tiebreaker (PK), иначе строки с одним timestamp пропускаются на границе страницы.
Cost: cursor только next/prev от известной точки — нельзя «страница 47» без отдельного count query.
Итог
Infinite scroll на live data — cursors; offset оставьте для admin UI с редкими deep jumps и пониманием trade-offs.