Вопрос проверяет понимание методов реализации стабильной постраничной навигации в API или базе данных, что критично для корректной работы пользовательских интерфейсов и предотвращения потери или дублирования данных.
Пагинация — это техника разделения большого набора данных на отдельные страницы для эффективной передачи и отображения. Консистентная пагинация гарантирует, что при последовательном запросе страниц пользователь не увидит пропущенные или дублированные элементы, даже если исходные данные изменяются (добавляются или удаляются записи) во время навигации.
Классический подход, где клиент передает параметры limit (сколько записей на странице) и offset (сколько записей пропустить). Например, запрос GET /items?limit=10&offset=20 вернет записи с 21-й по 30-ю.
-- SQL-пример с OFFSET
SELECT * FROM items
ORDER BY created_at
LIMIT 10 OFFSET 20;Проблема: Если между запросами первой и второй страницы в начало списка добавится новая запись, смещение "съедет", и пользователь может увидеть дубликат (элемент, который уже был на предыдущей странице) или пропустить один элемент.
Более надежный метод для динамических данных. Вместо числового смещения используется уникальный маркер (курсор), обычно основанный на уникальном и стабильном поле записи, например, ID или временной метке. Клиент запрашивает следующую страницу, передавая курсор последнего полученного элемента.
-- Пример: курсор на основе ID и времени
-- Первый запрос
SELECT * FROM items
WHERE status = 'active'
ORDER BY created_at DESC, id DESC
LIMIT 10;
-- Клиент сохраняет курсор последней записи: 'created_at=2023-10-05T12:00:00Z,id=12345'
-- Следующий запрос (передаем курсор)
SELECT * FROM items
WHERE status = 'active'
AND (created_at < '2023-10-05T12:00:00Z'
OR (created_at = '2023-10-05T12:00:00Z' AND id < 12345))
ORDER BY created_at DESC, id DESC
LIMIT 10;Преимущества: Устойчива к изменениям данных в уже пройденных частях набора. Новые записи, добавленные в начало, не влияют на навигацию по уже полученным страницам.
created_at вместе с ID для разрешения дублей по времени.next_cursor (или next_page_token), которое клиент использует для следующего запроса. Для первой страницы курсор не передается или передается пустым.previous_cursor или использовать симметричную логику.Вывод: Для большинства современных API, особенно с часто обновляемыми данными (ленты соцсетей, транзакции, логи), следует предпочесть cursor-based пагинацию, так как она обеспечивает консистентность. Offset-based подход подходит для статических или редко меняющихся данных, где важна простота реализации и возможность прыгать на произвольную страницу.