На любом собесе по system design и хайлоаду вас наверняка спросят про пагинацию. И вопрос этот с подвохом, т.к. на хайлоаде БД очень большие, с миллионами записей. Например, спросят как сделать бесконечную ленту последних постов с подгрузкой. И тут главное не обос****ться как я сделал на своем собесе 😂

Итак, что мы знаем про курсоры? В PostgreSQL есть самые настоящие курсосы! Они так и называются CURSOR. В постгресе они работают только внутри транзакций.
BEGIN;
DECLARE zhopa_cursor CURSOR FOR
  SELECT id, title, created_at FROM posts;

-- Получаем 10 строк:
FETCH 10 FROM zhopa_cursor;

-- Получаем еще следующие 10 строк сразу после места, где остановились до этого:
FETCH 10 FROM zhopa_cursor;

CLOSE zhopa_cursor;
COMMIT;

Обратите внимание, что обязательны транзакция и конкретное имя для курсора. Можно ли это использовать в вебе? Нет. Но я на собесе начал заливать про эти курсоры постгреса и про хранение имен курсоров, хотя непонятно как это все реализовать для веба. Типа не закрывать некоторое время транзакцию и держать открытой некоторое время пока идут http запросы? 😂

Короче, в веб разработке есть так называемые курсоры, которые никакими курсорами на самом деле не являются. Это обычные WHERE условия в SQL! Но за каким-то х***м это называется курсором.

Вот SQL получения первого списка постов для ленты:

SELECT id, title, created_at
FROM posts
ORDER BY created_at DESC, id DESC
LIMIT 20;

Далее браузер в http запросе для получения следующих 20 постов передает payload:

"last_created_at": "2026-01-15 12:30:00+00",
"last_id": 12345,

И бэк делает SQL запрос:

SELECT id, title, created_at
FROM posts
WHERE (created_at, id) < ($1, $2)
ORDER BY created_at DESC, id DESC
LIMIT 20;

Вот эта строка:
WHERE (created_at, id) < ($1, $2)
это и есть как бы наш курсор, хотя нифига это не курсор.

Такой запрос с псевдо-курсором намного быстрее, чем юзанье OFFSET когда постгрес читает все подходящие записи в таблице и тут же скипает часть их.
Показать полностью...