Ответ 1
В таблице есть первичный ключ. Используйте его.
Вместо LIMIT
и OFFSET
сделайте свой пейджинг с фильтром на первичном ключе. Вы намекнули на это со своим комментарием:
Пейджинг с использованием случайных чисел (добавьте "БОЛЬШЕ, ЧЕМ ЗАКАЗАТЬ", чтобы каждый запрос)
но нет ничего случайного о том, как вы должны это делать.
SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2
Разрешить клиенту указывать оба параметра, последний идентификатор, который он видел, и количество записей для извлечения. В вашем API должен быть либо заполнитель, либо дополнительный параметр, либо альтернативный вызов для "выборки первых n идентификаторов", где он исключает предложение WHERE
из запроса, но это тривиально.
Этот подход будет использовать довольно эффективную проверку индекса для получения записей в порядке, обычно избегая сортировки или необходимости итерации по всем пропущенным записям. Клиент может решить, сколько строк он хочет сразу.
Этот подход отличается от подхода LIMIT
и OFFSET
одним ключевым способом: одновременная модификация. Если вы INSERT
в таблице с ключом ниже ключа, который уже видел какой-либо клиент, этот подход вообще не изменит его результаты, тогда как подход OFFSET
повторит строку. Точно так же, если вы DELETE
строку с более низким, чем уже видели ID, результаты этого подхода не изменятся, тогда как OFFSET
пропустит невидимую строку. Однако нет никакой разницы только для таблиц с добавлением только с сгенерированными ключами.
Если вы заранее знаете, что клиенту понадобится весь набор результатов, наиболее эффективная вещь - просто отправить им весь результирующий набор без этого пейджингового бизнеса. Это, где я буду использовать курсор. Прочитайте строки из БД и отправьте их клиенту так быстро, как клиент их примет. Этот API должен будет устанавливать ограничения на то, насколько медленным был клиент, чтобы избежать чрезмерной нагрузки на бэкэнд; для медленного клиента я бы, вероятно, переключился на пейджинг (как описано выше) или спулал весь вывод курсора во временный файл и закрыл соединение с БД.
Важные оговорки:
- Требуется, чтобы индекс
UNIQUE
/UNIQUE
илиPRIMARY KEY
был надежным - Различные режимы одновременной модификации для ограничения/смещения, см. выше