🩼 Осторожно, грабли!
Завершаем цикл заметок по пагинации граблями, на которые можно наступить.
🔸 N+1 проблема при курсорной пагинации. Вы получили 20 id из основного запроса, но для каждой записи нужно подтянуть связанные данные (например, имя автора). Решение: жадная загрузка всех необходимых данных в одном ответе.
🔸 Неуникальный курсор. Если поле курсора (например, created_at) не уникально, записи могут "потеряться" на стыке страниц. В таких случаях используйте уникальный составной ключ, например, created_at и id.
🔸 Слишком большой page_size. Большой размер страницы может убить и БД, и сеть, и клиент. Вводите разумные ограничения и валидируйте входные параметры.
🔸 Отсутствие сортировки. Всегда явно указывайте order_by. Без этого порядок записей не гарантирован, и пагинация будет работать некорректно. Базы данных не обязаны возвращать данные в порядке первичного ключа по умолчанию.
🔸 Совместимость с фильтрацией и поиском. Пагинация должна корректно работать в сочетании с любыми фильтрами. Убедитесь, что индексы покрывают комбинацию полей для фильтрации и сортировки.
🔸 Подсчет количества записей Для Offset-пагинации запрос COUNT(*) на больших таблицах может быть очень медленным. Рассмотрите:
- Приблизительные подсчеты (например, из статистики БД).
- Отказ от подсчета общего числа страниц ("Показать еще" вместо "Страница 5 из 1000").
- Кеширование значения.
♎️ Чеклист для проектирования
📍 Определил поведение пользователя: произвольный доступ или последовательное чтение?
📍 Выбрал тип пагинации: смещение или курсор исходя из объема данных.
📍 Определил поля для сортировки и, если нужно курсора, убедился в их уникальности.
📍 Спроектировал контракт API: структура запроса (параметры) и ответа (метаданные).
📍 Учел производительность: проверил наличие нужных индексов, ввел ограничения на размер пакета.
📍 Учел комбинацию с фильтрами и поиском.
📍 Продумал обработку крайних случаев: пустой результат, последняя страница, невалидный курсор.
📍 Задокументировал принятые решения и ограничения для команды разработки.
У меня получилось вас убедить, что пагинация — это не просто "сделать запрос с LIMIT/OFFSET"?
Это комплексное архитектурное решение, которое напрямую влияет на отзывчивость приложения.
Post #103
98