Как стать автором
Поиск
Написать публикацию
Обновить

Оптимизация работы с REST API: когда и как использовать пагинацию (+ простой пример на Python)

Уровень сложностиПростой
Время на прочтение14 мин
Количество просмотров8.5K
Всего голосов 46: ↑45 и ↓1+54
Комментарии6

Комментарии 6

При работе с большими объёмами данных в PostgreSQL запросы с OFFSET 1M стали вызывать задержки в несколько секунд. Как я понимаю и читал, курсорная пагинация должна как то решать эту проблему. Действительно ли это оптимальное решение?

Cursor снижает нагрузку в сравнении с , но и тут есть свои ограничения. Далеко ходить не нужно, если сортировка выполняется по неуникальному полю, могут возникать дубликаты или пропуски в данных.

Кроме того, курсоры зависят от актуальности данных на момент выполнения — при изменении записей между запросами возможны расхождения. Однако для классической пагинации с произвольным доступом OFFSET всё ещё применяется. Вы сталкивались в вашей практике с ситуациями, когда курсорная пагинация оказалась неудобной?

Да, в нашем случае данные обновлялись настолько быстро, что курсор не успевал актуализироваться и вообще так выходило что часть записей терялась между страницами. В результате мы после планерки решили перейтии на keyset-пагинацию, зафиксировав снэпшот транзакции через REPEATABLE READ с использованием неизменяемого идентиф. В целом из плюсов это позволило сократить время отклика до 150 мс, ноо потребовалось доработать клиентскую логику для корректной передачи и сохранения состояния курсора. Например, добавили хэширование последнего полученного ID для предотвращения конфликтов.

(извините заранее, ответ очень тупой, "по букварю" но, м/б, я вас не так понял)
Кажется, зависит от того, что конкретно в PostgreSQL у вас происходит, надо план выполнения смотреть. Особенно если там сортировка по чему-нибудь, что Постгри не умеет оптимизировать - по неиндексированному полю, по вычислимому выражению, по не тому индексу что использовался в отборе по Where.

Я с Постгри совсем не работал, но MySQL так умеет делать вообще легко. Предположим, там получилось в SQL limit 100 offset 1M, а базе приходится 1M+100 строк отобрать, потом 1M выкинуть; подобная ситуация может ощутимо тормозить на больших оффсетах. Плюс, будет заметно, если "цена" выборки одной строки большая - какой-нибудь LEFT JOIN или dependent subquery. Или "перекошенный" индекс, например, есть флажок логического удаления записи и просьба к SQL-ю выбрать только неудалённые.

(Достоинства пажинации тут все равно присутствуют - они в том, что по сетке этот 1М передавать не надо. Но база, тем не менее, может захотеть этот лишний 1М вычислить)

(извините заранее, ответ очень тупой, "по букварю" но, м/б, я вас не так понял)
Кажется, зависит от того, что конкретно в PostgreSQL у вас происходит, надо план выполнения смотреть. Особенно если там сортировка по чему-нибудь, что Постгри не умеет оптимизировать - по неиндексированному полю, по вычислимому выражению, по не тому индексу что использовался в отборе по Where.

Я с Постгри совсем не работал, но MySQL так умеет делать вообще легко. Предположим, там получилось в SQL limit 100 offset 1M, а базе приходится 1M+100 строк отобрать, потом 1M выкинуть; подобная ситуация может ощутимо тормозить на больших оффсетах. Плюс, будет заметно, если "цена" выборки одной строки большая - какой-нибудь LEFT JOIN или dependent subquery. Или "перекошенный" индекс, например, есть флажок логического удаления записи и просьба к SQL-ю выбрать только неудалённые.

(Достоинства пажинации тут все равно присутствуют - они в том, что по сетке этот 1М передавать не надо. Но база, тем не менее, может захотеть этот лишний 1М вычислить)

Пагинация - это какой-то общеупотребимый термин? Странитизация? Постраничные запросы? Обычное дело при работе с огромными объемами - запрашивать данные кусками (страницами). Это на сервере можно попросить сразу всё и не заметить, а когда память ограничена - автоматически начинаешь этим пользоваться.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий