Пагинация в БД без offset. Работаем с запросами

Поділитися
Вставка
  • Опубліковано 26 січ 2022
  • В этом ролике мы посмотрим на способ организации пагинации без ключевого слова offset.
    Пагинация это порционная выдача данных из БД.
    Больше обо мне и курсах можно прочитать здесь:
    artofedu.org/
    Приятного просмотра!
    Use the Index, Luke!
    use-the-index-luke.com/
    May the index be with you!
    Поддержи выход новых видео на Патреоне!
    / theartofdevelopment
    Другие видео:
    Уроки по Golang. Advanced. REST API. Вебсервер.
    • Уроки по Golang. Advan...
    Изучаем Python. Урок 1. Основы. Бонус: Пишем приложение на FastAPI • Изучаем Python. Урок 1...
    Изучаем Golang. Урок 1. Основы + веб-сервер в 3 строки в конце урока! • Изучаем Golang. Урок 1...
    Разработка системы заметок на Python, Golang и микросервисы в 2021 году • Разработка системы зам...
    Как стать разработчиком. Часть 1 • Как стать разработчико...
    Что такое микросервисы за 200 секунд • Что такое микросервисы...
    Что такое Apache Kafka за 200 секунд • Что такое Apache Kafka...
    Telegram Group: t.me/theartofdevel
    VK: theartofdevel
    Дружественный Golang чат: t.me/gogolang
    ----
    Меня зовут Артур Карапетов и я занимаюсь всем, что связано с разработкой. Я создаю высоконагруженные информационные системы, стартапы, занимаюсь личным обучением людей в сфере разработки (программисты, аналитики, системные администраторы), также я помогаю компаниям и стартапам с обучением людей работать и повышением их квалификации, об этом можно почитать здесь: mitkadr.ru.
    На этом канале я выкладываю ролики на интересующие меня темы, здесь можно найти серию роликов про создание информационной системы с нуля, а также можно найти серию уроков по языкам, которые я люблю. Добро пожаловать и хорошего просмотра!
    #golang #урок #restapi #rest #микросервисы #microservices #jetbrains #goland #tutorial #голенг #development #howto #learnbasics #coding #programming #изучаемIT #программирование #разработка
  • Наука та технологія

КОМЕНТАРІ • 33

  • @user-rz6xv8zt8n
    @user-rz6xv8zt8n 2 роки тому +2

    Уже несколько лет применяем подобную пагинацию на своих проектах в компании. Mysql по обычному числовому идентификатору (таблицы более 500к записей) и в MongoDB по ObjectId (коллекции на пару десятков миллионов записей) - работает отлично. А вот в одном из проектов в таблице на 200к записей пагинация через обычный limit\offset стандартными средствами php-фреймворка. И вот там очень ощущается деградация скорости выполнения запроса ближе к последней трети. Наверное, стоит еще отметить, что для поля для курсора требуется индекс. Спасибо за видео!

    • @petery6775
      @petery6775 10 місяців тому

      а почему нельзя просто ID сравнивать ? сделав его big int ? без кортежного сравнения и обойтись 1 полем

  • @Rryowa
    @Rryowa Місяць тому +1

    Господь храни тебя и твой канал, ничего более информативного и интересного по гошке не видел, надеюсь ты когда-нибудь вернешься...

  • @delay_gryaz_chisto
    @delay_gryaz_chisto 2 роки тому +10

    называется это курсорная пагинация. проще объяснить так: мы ставим курсор на какую-то последнюю запись(которую приняли в квери-параметре хендлера из урла), и говорим: ОТДАЙ НАМ СЛЕДУЮЩИЕ %LIMIT%(предположим, три). ну оно и отдает. тем самым не прогружая всю БД как в случае с оффсетом. и считается хорошей практикой отдавать в ответе клиенту в жсоне поля next и prev путь на следующую/предыдущую страницу, где квери-параметры(в ссылке) next/prev - это base64 айдишников.
    ну а если бы id был интом, то сравнение с датой было бы лишнее лишнее. инта достаточно.
    за видео спасибо.

  • @sovrinfo
    @sovrinfo Рік тому +1

    Спасибо за видео. Коммент в поддержку!

  • @dmitriyobidin6049
    @dmitriyobidin6049 2 роки тому +4

    Интересный приём, действительно должно быстрее работать.
    Пара вопросов возникает:
    1) Guid в качестве уникального идентификатора. При использовании гуида не стоит ожидать, что порядок выбора записей для пагинации будет совпадать с порядком того, как записи лежат в таблице. Хотя по факту работать будет и записи не пропустит(вроде как), но семантически может выглядеть странно, например, порядок книг будет выводится не в алфавитном порядке(не в том порядке, как мы их добавляли).
    2) Было бы более показательно и всеообъемлюще, если бы в примере был не таймстемп, а просто дата. Т.е. если бы в примере были записи в одинаковыми значениями в поле даты. А то так получается, что у всех записей во всех полях значения уникальные. Тут хоть по чему сортируй - получишь корректную(с точки зрения отсутствия пропусков) пагинацию.
    3) Получается что необходимо хранить стейт на стороне сервера? Или наоборот со стороны клиента передавать значения из последней полученной записи?

  • @andreybalatsan9336
    @andreybalatsan9336 11 днів тому +1

    Я только начинаю изучать гошку, для меня выглядит это как игра в наперстки с уличным жуликом. И я такой - Это магия... Но в конце всё понял

  • @MaxShcherbakov
    @MaxShcherbakov 2 роки тому +14

    Идентификатор в примере либо лишний, либо не того типа, ибо сравнение картежа, где есть UUID не имеет смысла, имхо. В примере с сайта что вы показывали скорее всего используется числовой идентификатор, скорее всего автогенерация по Seq, чтобы каждая новая запись имела следующий номер, тогда сравнение картежей имеет смысл.

  • @TheArtofDevelopment
    @TheArtofDevelopment  2 роки тому +6

    Что скажете по поводу такой пагинации?
    P.S. на этот раз вместо вебки телефон, но помешали тени. некст тайм включу софтбоксы

  • @rumartru
    @rumartru 2 роки тому +2

    Спасибо! Теперь я знаю почему у меня борода не растет 😂

  • @bunchatests
    @bunchatests 4 місяці тому

    интересно, можно ли сделать пагинацию без ORDER BY?

  • @sergeyfilatov3027
    @sergeyfilatov3027 2 роки тому +2

    Получается что вместо
    select * from video order by created desc offset 0 limit 10
    нам предлагают делать
    select * from video where created < {last_created} order by created desc limit 10
    что означает что на клиенте нужно хранить не page_id, а данные всех полей по которым идет сортировка
    Ну ок, классно, что есть такой вариант.
    Но я думаю это уже немного относится к ранней оптимизации.
    То есть, я бы так делал если бы я реально понимал, что для меня это важно, в других случаях бы не заморачивался.
    p. s. про кортежное сравнение первый раз узнал xD

    • @BabaykaMoscow
      @BabaykaMoscow 2 роки тому

      А ты попробуй сгенери таблицу с 10 миллионами записей и попробуй бабахнуть в ней оффсетом начиная с 9 миллионной записи. И каунт до кучи сделай. И сразу станет понятно, что все это перестаёт нормально работать :)

  • @alekssjeva951
    @alekssjeva951 Рік тому +1

    Этот вариант не подходит, если нужна классическая пагинация (в виде ссылок на страницы пагинации). А так давно заметил, что даже при небольших значениях OFFSET (10-15), запрос в MySQL выполняется значительно медленнее, чем без OFFSET

  • @xtech3408
    @xtech3408 Рік тому +1

    Почему во время интерпретации на ключевое слово offset, СУБД под капотом не делает тоже самое, если так быстрее? И что такого делает offset, что получается медленнее. СУБД типа сначала всю таблицу выгружает, а потом лишнее выкидывает? Поэтому?

    • @alvcode3764
      @alvcode3764 4 місяці тому

      потому что субд не ванга, откуда она знает, что ей делать надо. на то и нужны команды. offset по сути отсчитывает все записи до указанного смещения. если задал offset 100000 limit 10, то по сути базе надо отсчитать все записи, пока не будет по счету 100к и начиная со следующей отдаст 10 записей. а существует какое-то доп.условие WHERE, то скорость намного ухудшается. например когда надо достать просто 10 записей по условию WHERE, то база найдет первые 10 попавшихся и отдаст их, а тут она должна найти все 100к подходящие под условие WHERE и только следующие 10 отдать

  • @ksivvi0
    @ksivvi0 Рік тому +1

    привет! немного критики, не обессудь...
    видео кажется затянутым, и если бы я совсем не понимал данную тему, вряд-ли бы понял.
    т к в данном видео ничего не сказано про индексы, то лучше использовать limit offset)

  • @eamarc
    @eamarc 2 роки тому +3

    Можно всю эту логику в функцию на БД засунуть. Типа `SELECT get_books(1, 10) ` чтоб было хорошо и беку и фронту.

  • @petery6775
    @petery6775 10 місяців тому

    а почему нельзя просто ID сравнивать ? сделав его big int ? без кортежного сравнения и обойтись 1 полем

  • @user-px3tp9kh3i
    @user-px3tp9kh3i Рік тому +1

    А как на клиенте показывать сколько всего есть страниц, если не использовать count(*)?

    • @TheArtofDevelopment
      @TheArtofDevelopment  Рік тому

      А точно ли есть такая задача?
      Обычно эта цифра на самом деле не нужна, если коллекция огромная (сотни тысяч записей), ну если вы не гугл, конечно.
      Но если нужна - то конечно делать count(*)

    • @user-px3tp9kh3i
      @user-px3tp9kh3i Рік тому

      @@TheArtofDevelopment Спасибо!

  • @kumb61
    @kumb61 Рік тому +1

    Очень долго, это можно было в минут 5 уложить.
    А так идея интересная, получается это на беке нужно всегда сохранять ключи последней записи?
    Думаю что скорость достигается за счет того, что при миллионах записей вместо последовательного пропуска от OFFSET отрабатывается какой нибудь бинарный поиск по индексу.

  • @ruslanroot
    @ruslanroot 2 роки тому +2

    главное чтоб пользователь не нажал переход на 69 страницу, сразу с первой ;)

    • @denisromanov9367
      @denisromanov9367 2 роки тому +2

      Это просто порционная выдача пачки данных, а не "навигация" по пагинации.
      В хайлоад на 69 странице, раз в долю секунды будут меняться данные ;)

  • @aleksandrsu998
    @aleksandrsu998 2 роки тому +1

    Это всё хорошо, но мы не можем взять и перейти сразу на тысячную страницу. И не знаем их общее количество.

    • @TheArtofDevelopment
      @TheArtofDevelopment  2 роки тому

      а есть такая задача? если есть ее можно решить иначе

    • @no1621name
      @no1621name Рік тому +1

      @@TheArtofDevelopment не подскажите, как?

    • @TheArtofDevelopment
      @TheArtofDevelopment  Рік тому +1

      стандартно, через limit и offset

    • @no1621name
      @no1621name Рік тому

      @@TheArtofDevelopment хорошо, спасибо

  • @user-br3hw1us7k
    @user-br3hw1us7k Рік тому +1

    Не могу понять что так все любят пихать в поле примари кей тип uuid когда он в бд 128 бит занимает, что как бы много, тот же биг инт будет занимать в 2 раза меньше

    • @vadimburavlev4773
      @vadimburavlev4773 9 місяців тому

      потому что автоинкримент на id не всегда решает все виды задач.
      в распределенных действительно больших системах получать автоинкрементный id становится большой болью. когда нужно спрятать последовательность выдачи id тоже подходит uuid, его можно получать с timestamp - uuid 7 версии, есть uuid с hash. Все зависит от решаемой задачи.