Как стать автором
Обновить

Как мы перешли с оффсетной пагинации на курсорную, или о проблемах динамической фильтрации

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров3.2K
Всего голосов 8: ↑6 и ↓2+6
Комментарии13

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

Довольно странно в статье, в названии которой прямо фигурирует курсорная пагинация, не найти ни одного упоминания курсорной пагинации.

Вы про курсоры в БД?

Да, из названия ожидаешь прочитать историю внедрения курсорной пагинации, но в тексте речь идёт о пагинации на основе упорядоченного набора ключей.

И совсем не ясно, какие фильтры вы применяете к полученным из БД данным, что эти фильтры нельзя применить на уровне самой БД. Вот это было бы действительно интересно.

Если честно, разницы всё равно не понял.

Вот курсорная пагинация в ларавел: на фронт отдаём строку с курсором, а по факту это тот же упорядоченных набор ключей:where id > 15 order by id asc limit 15.

Можно пример чем курсорная пагинация отличается от "на основе упорядоченного набора ключей"?

P.S. я не автор и мне самому интересно почему фильтрация не в бд.

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

Просмотрел ссылку, которую вы скинули, и таки да - всё встало на свои места. Ларавель, похоже, называют курсорной пагинацией как раз пагинацию по упорядоченному набору ключей, просто в параметрах запроса вместо страницы нужно передавать зашифрованную строку, которую они называют курсором. Интересно, АпиПалтформа тоже под курсором понимают не курсор в БД?

я не автор

Сорри, почему-то я решил что статься ваша :)

Вы приводите ссылку на Laravel и курсорную пагинацию в нём же. Наша реализация сделала примерно по такому же принципу, но на Python (в силу языка мы не можем использовать Laravel). Насчет

И совсем не ясно, какие фильтры вы применяете к полученным из БД данным, что эти фильтры нельзя применить на уровне самой БД

К сожалению, фильтровать данные на уровне самой БД нам на текущий момент не позволяет архитектура приложения

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

В одном из проектов как раз реализовывал подобную курсорную пагинацию правда она там была в обе стороны. Обычно при долгой прокрутке страницы, с доскролом, на странице начнет отображаться так много записей что сама страница начнет тормозить и подлагивать. Чтобы этого избежать курсорная подгрузка реализована в обе стороны: при подгрузке третей и более страницы верхние данные удаляются. И наоборот. При прокрутке на верх подгружаются записи которые были удалены ранее, а снизу записи стираются.

А как сделано у вас. Курсоры в обе стороны или только в одну?

Сейчас у нас курсоры только в одну сторону, так как в обратную пока не было необходимости. Но технически мы это возможность для клиентов (веб, ios, android) рассматривали и учитывали, поэтому добавить её будет не сложно

Так в оффсете запомните id/прочее первого элемента и передавайте его в lte/gte фильтр. Проблема только если внутри выборки меняются данные что влияет на порядок сортировки

Самое интересное в такой пагинации это составные индексы с указанием сортировки индекса. За счёт чего и получается быстро находить нужную точку. К сожалению об этом ничего не написано.

Снова отфильтровываем и повторяем цикл, пока не наберем нужное количество + 1 (почему +1 расскажу чуть ниже), либо пока не сходим за донабором пять раз. Количество попыток донабора было выбрано эмпирическим путем, потому что для большинства артистов этого должно было хватить.


При этом в итоге можно получить 0 записей.

Решение которое будет идеально для пользователя это загнать всё в одну базу. Это может быть дополнительная база, которая хранит копию данных предназначенную именно для этих запросов. Если фильтры редко меняются, то можно посмотреть на nosql решения, где можно положить все поля для фильтрации в один документ например OpenSearch.

Для компании такое решение не бесплатное. Нужно много места и новый сервер(ы), проблемы поддержания данных в актуальном состоянии (новые треки найдутся не сразу), ну и работа разработчиков.

Прости если ошибаюсь, но разве во тут не схожий подход описан?

А то, что у вас среди релизов одного исполнителя выдаются релизы совсем других жанров и других одноимённых исполнителей, это тоже из-за особенностей фильтрации? Или просто привязали треки по совпадению имён исполнителей? (пример)

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