Зашто вам је потребна инструментална подршка за пагинацију на кључевима?

Здраво свима! Ја сам бацкенд програмер који пише микросервисе у Јава + Спринг. Радим у једном од интерних тимова за развој производа у Тинкофф-у.

Зашто вам је потребна инструментална подршка за пагинацију на кључевима?

У нашем тиму се често поставља питање оптимизације упита у ДБМС. Увек желите да будете мало бржи, али не можете увек да прођете са промишљено конструисаним индексима – морате да потражите нека решења. Током једног од ових лутања по мрежи у потрази за разумним оптимизацијама при раду са базама података, пронашао сам Бескрајно користан блог Маркуса Вајнанда, аутор књиге СКЛ Перформанце Екплаинед. Ово је онај ретки тип блога у коме можете читати све чланке за редом.

Желео бих да вам преведем кратак Маркусов чланак. То се донекле може назвати манифестом који настоји да скрене пажњу на стари, али још увек релевантан проблем извођења офсет операције према СКЛ стандарду.

На неким местима ћу аутора допунити објашњењима и коментарима. Сва таква места ћу називати „приближно“. ради веће јасноће

Мали увод

Мислим да многи људи знају колико је проблематичан и спор рад са одабиром страница путем офсета. Да ли сте знали да се може прилично лако заменити ефикаснијим дизајном?

Дакле, кључна реч оффсет говори бази података да прескочи првих н записа у захтеву. Међутим, база података и даље треба да прочита ових првих н записа са диска, у датом редоследу (напомена: примени сортирање ако је наведено), па ће тек тада бити могуће вратити записе од н+1 па надаље. Најинтересантније је да проблем није у конкретној имплементацији у ДБМС, већ у оригиналној дефиницији према стандарду:

…редови се прво сортирају према , а затим се ограничавају испуштањем броја редова наведених у од почетка…
-СКЛ:2016, 2. део, 4.15.3 Изведене табеле (напомена: тренутно најчешће коришћени стандард)

Кључна ствар овде је да офсет узима један параметар - број записа које треба прескочити, и то је то. Пратећи ову дефиницију, ДБМС може само да преузме све записе, а затим одбаци непотребне. Очигледно, ова дефиниција офсета нас тера на додатни посао. И није чак ни важно да ли је СКЛ или НоСКЛ.

Само још мало бола

Проблеми са офсетом се ту не завршавају, а ево и зашто. Ако, између читања две странице података са диска, друга операција убаци нови запис, шта ће се догодити у овом случају?

Зашто вам је потребна инструментална подршка за пагинацију на кључевима?

Када се офсет користи за прескакање записа са претходних страница, у ситуацији додавања новог записа између читања различитих страница, највероватније ћете добити дупликате (напомена: ово је могуће када читамо страницу по страницу користећи редослед по конструкцији, затим у средини нашег излаза може добити нови унос).

Слика јасно приказује ову ситуацију. База чита првих 10 записа, након чега се убацује нови запис, који помера све прочитане записе за 1. Затим база узима нову страницу од следећих 10 записа и почиње не од 11. како би требало, већ од 10., дуплирање овог записа. Постоје и друге аномалије повезане са употребом овог израза, али ово је најчешће.

Као што смо већ сазнали, то нису проблеми одређене ДБМС или њихове имплементације. Проблем је у дефинисању пагинације према СКЛ стандарду. Ми говоримо ДБМС-у коју страницу да преузме или колико записа да прескочи. База података једноставно није у стању да оптимизује такав захтев, јер има премало информација за ово.

Такође је вредно појаснити да ово није проблем са специфичном кључном речи, већ са семантиком упита. Постоји још неколико синтакса које су идентичне по својој проблематичној природи:

  • Кључна реч оффсет је као што је раније поменуто.
  • Конструкција од две кључне речи лимит [оффсет] (иако ограничење само по себи није тако лоше).
  • Филтрирање према доњим границама, на основу нумерисања редова (на пример, ров_нумбер(), ровнум, итд.).

Сви ови изрази вам једноставно говоре колико редова да прескочите, без додатних информација или контекста.

Касније у овом чланку, кључна реч оффсет се користи као резиме свих ових опција.

Живот без ОФФСЕТ-а

Сада замислимо какав би наш свет изгледао без свих ових проблема. Испоставило се да живот без померања није тако тежак: са селекцијом можете изабрати само оне редове које још нисмо видели (напомена: то јест, оне који нису били на претходној страници), користећи услов где.

У овом случају полазимо од чињенице да се одабири извршавају на уређеном скупу (стари добри ред би). Пошто имамо уређен скуп, можемо користити прилично једноставан филтер да добијемо само податке који се налазе иза последњег записа претходне странице:

    SELECT ...
    FROM ...
    WHERE ...
    AND id < ?last_seen_id
    ORDER BY id DESC
    FETCH FIRST 10 ROWS ONLY

То је цео принцип овог приступа. Наравно, ствари постају забавније када се сортирате по многим колонама, али идеја је и даље иста. Важно је напоменути да је овај дизајн применљив на многе NoSQL-Одлуке.

Овај приступ се назива методом тражења или пагинацијом скупа кључева. Решава проблем плутајућег резултата (напомена: раније је описана ситуација са писањем између читања страница) и, наравно, оно што сви волимо, ради брже и стабилније од класичног офсета. Стабилност лежи у чињеници да се време обраде захтева не повећава пропорционално броју тражене табеле (напомена: ако желите да сазнате више о раду различитих приступа пагинацији, можете погледај кроз излагање аутора. Тамо такође можете пронаћи упоредна мерила за различите методе).

Један од слајдова говори о томета пагинација по кључевима, наравно, није свемогућа – она има своја ограничења. Најзначајније је то што она нема могућност читања насумичних страница (напомена: недоследно). Међутим, у ери бесконачног скроловања (напомена: на предњем крају), то није толики проблем. Одређивање броја странице за клик је ионако лоша одлука у дизајну корисничког интерфејса (напомена: мишљење аутора чланка).

Шта је са алатима?

Пагинација на кључевима често није погодна због недостатка инструменталне подршке за овај метод. Већина развојних алата, укључујући различите оквире, не дозвољавају вам да изаберете тачно како ће се извршити пагинација.

Ситуацију отежава чињеница да описани метод захтева подршку од краја до краја у технологијама које се користе – од ДБМС-а до извршавања АЈАКС захтева у претраживачу са бесконачним померањем. Уместо да наведете само број странице, сада морате да наведете скуп кључева за све странице одједном.

Међутим, број оквира који подржавају пагинацију на кључевима постепено расте. Ево шта имамо у овом тренутку:

(Напомена: неке везе су уклоњене због чињенице да у време превођења неке библиотеке нису ажуриране од 2017-2018. Ако сте заинтересовани, можете погледати оригинални извор.)

Управо у овом тренутку ваша помоћ је потребна. Ако развијате или подржавате оквир који користи пагинацију на било који начин, онда вас молим, позивам, преклињем вас да пружите изворну подршку за пагинацију на кључевима. Ако имате питања или вам је потребна помоћ, радо ћу вам помоћи (форум, Twitter, Контакт формулар) (напомена: из мог искуства са Маркусом, могу рећи да је он заиста одушевљен ширењем ове теме).

Ако користите готова решења за која мислите да су вредна подршке за пагинацију по кључевима, направите захтев или чак понудите готово решење, ако је могуће. Такође можете повезати овај чланак.

Закључак

Разлог зашто тако једноставан и користан приступ као што је пагинација по кључевима није широко распрострањен није то што га је технички тешко имплементирати или захтева велики напор. Главни разлог је то што су многи навикли да виде и раде са офсетом - овај приступ диктира сам стандард.

Као резултат тога, мало људи размишља о промени приступа пагинацији и због тога се инструментална подршка оквира и библиотека слабо развија. Стога, ако су вам идеја и циљ пагинације без офсета блиски, помозите да је проширите!

Извор: https://use-the-index-luke.com/no-offset
Аутор: Маркус Винанд

Извор: ввв.хабр.цом

Додај коментар