Ответ
Для пагинации на стороне БД используют LIMIT и OFFSET в SQL-запросах. Например:
SELECT * FROM products
ORDER BY id
LIMIT 10 OFFSET 20; -- пропускаем 20 записей, берем 10
Но OFFSET неэффективен на больших данных - чем дальше, тем медленнее. Альтернатива - ключевой метод:
SELECT * FROM products
WHERE id > 50 -- последний полученный ID
ORDER BY id
LIMIT 10;
На фронте храним последний загруженный ID или другую уникальную метку. Это быстрее, так как БД использует индексы.
Для реализации в API обычно передают параметры:
limit- количество элементовafterилиbefore- курсор для пагинации
Пример запроса:
GET /api/products?limit=10&after=50
Ответ 18+ 🔞
А, ну ты глянь, какие у нас тут проблемы с пагинацией! Сидят, блядь, разработчики, думают: "О, да я щас как накручу OFFSET 1000000, и всё будет летать!" А потом, сука, через месяц приложение еле ползает, и все удивляются — пиздец, откуда тормоза?
Так вот, слушай сюда, пока не поздно. Есть два пути, и один из них — дорога в ад.
Первый путь, для ленивых и наивных (он же "пиздец как тормозит"):
Ты просто пишешь в запросе LIMIT и OFFSET. Типа, "дай мне 10 штук, начиная с 20-й". Выглядит просто, да?
SELECT * FROM products
ORDER BY id
LIMIT 10 OFFSET 20; -- пропускаем 20 записей, берем 10
И всё вроде бы работает, пока у тебя там 100 товаров. Но представь, что товаров — овердохуища. И кто-то решил посмотреть на 10000-ю страницу. Что делает БД? Она, сука, должна пройтись по всем этим 10000 10 записей, чтобы их пропустить*, и только потом взять свои 10. Это как искать иголку в стоге сена, предварительно пересчитав всё сено в стоге. Эффективность — ноль ебать. Запрос начинает тормозить хуже старого деда на костылях.
Второй путь, для умных и красивых (он же "ключевой метод" или "курсорная пагинация"):
Тут мы не тупо пропускаем, а говорим БД: "Эй, дай мне 10 записей, но только тех, у которых id больше, чем последний, который я уже видел!". Блядь, и это гениально просто.
SELECT * FROM products
WHERE id > 50 -- последний полученный ID
ORDER BY id
LIMIT 10;
Почему это быстрее? Потому что у id, скорее всего, есть индекс! База данных не шарится по всей таблице, а сразу прыгает в нужное место по индексу и берёт следующие записи. Скорость — просто ёперный театр!
А как это на практике, в рот меня чих-пых?
На фронте ты не считаешь страницы, а хранишь последний загруженный id (или другую уникальную метку, по которой сортируешь). Это твой курсор.
В API делаешь красивые параметры, а не page=100500:
limit— сколько элементов (всё как у людей).after— курсор, после которого нужно искать (например, последний известный id).before— можно и до курсора, если надо назад.
Пример запроса будет выглядеть солидно и не вызывать инфаркт у базы данных:
GET /api/products?limit=10&after=50
Вот и вся магия. Перестаньте, блядь, использовать OFFSET на больших данных, а то я чувствую подозрение, что вы специально хотите положить продакшен. Используйте ключевой метод, и пусть ваше приложение летает, а не ползает, как мартышлюшка по асфальту в январе.