Zakaj potrebujete instrumentalno podporo za paginacijo na ključih?

Pozdravljeni vsi skupaj! Sem zaledni razvijalec, ki piše mikrostoritve v Java + Spring. Delam v eni od internih ekip za razvoj izdelkov v Tinkoffu.

Zakaj potrebujete instrumentalno podporo za paginacijo na ključih?

V naši ekipi se pogosto pojavlja vprašanje optimizacije poizvedb v DBMS. Vedno želite biti nekoliko hitrejši, vendar ne morete vedno preživeti s premišljeno sestavljenimi indeksi – poiskati morate rešitve. Med enim od teh tavanj po spletu v iskanju razumnih optimizacij pri delu z bazami podatkov sem našel Neskončno koristen blog Marcusa Wynanda, avtor knjige SQL Performance Explained. To je tista redka vrsta bloga, v katerem lahko preberete vse članke po vrsti.

Za vas bi rad prevedel kratek Marcusov članek. Do neke mere ga lahko imenujemo manifest, ki skuša opozoriti na staro, a še vedno aktualno problematiko izvajanja operacije zamika po standardu SQL.

Ponekod bom avtorja dopolnil s pojasnili in komentarji. Vsa taka mesta bom imenoval "približno." za večjo jasnost

Majhen uvod

Mislim, da veliko ljudi ve, kako problematično in počasno je delo z izbiro strani prek offseta. Ali ste vedeli, da ga je mogoče enostavno nadomestiti z učinkovitejšim dizajnom?

Torej ključna beseda offset pove bazi podatkov, naj preskoči prvih n zapisov v zahtevi. Vendar pa mora zbirka podatkov še vedno prebrati teh prvih n zapisov z diska, v danem vrstnem redu (opomba: uporabite razvrščanje, če je navedeno), in šele nato bo mogoče vrniti zapise od n+1 dalje. Najbolj zanimivo pa je, da težava ni v specifični implementaciji v DBMS, ampak v originalni definiciji po standardu:

... so vrstice najprej razvrščene glede na in nato omejite tako, da izpustite število vrstic, določeno v od začetka...
-SQL:2016, 2. del, 4.15.3 Izpeljane tabele (opomba: trenutno najbolj uporabljen standard)

Ključna točka pri tem je, da zamik vzame en sam parameter - število zapisov, ki jih je treba preskočiti, in to je to. Po tej definiciji lahko DBMS samo pridobi vse zapise in nato zavrže nepotrebne. Očitno nas ta definicija odmika sili k dodatnemu delu. In sploh ni pomembno, ali je SQL ali NoSQL.

Samo še malo bolečine

Težave z odmikom se tu ne končajo in tukaj je razlog. Če med branjem dveh strani podatkov z diska druga operacija vstavi nov zapis, kaj se bo zgodilo v tem primeru?

Zakaj potrebujete instrumentalno podporo za paginacijo na ključih?

Ko se odmik uporablja za preskok zapisov s prejšnjih strani, boste v primeru dodajanja novega zapisa med branji različnih strani najverjetneje dobili dvojnike (opomba: to je možno, ko beremo stran za stranjo z vrstnim redom po konstrukciji, potem sredi našega izpisa lahko dobi nov vnos).

Slika jasno prikazuje to situacijo. Baza prebere prvih 10 zapisov, nato pa se vstavi nov zapis, ki zamakne vse prebrane zapise za 1. Nato baza vzame novo stran od naslednjih 10 zapisov in ne začne od 11., kot bi morala, ampak od 10., podvajanje tega zapisa. Obstajajo tudi druge anomalije, povezane z uporabo tega izraza, vendar je ta najpogostejša.

Kot smo že ugotovili, ne gre za težave s posebnim DBMS ali njihovimi implementacijami. Težava je v definiranju paginacije po standardu SQL. DBMS povemo, katero stran naj pridobi ali koliko zapisov naj preskoči. Baza podatkov preprosto ne more optimizirati takšne zahteve, saj je za to premalo informacij.

Prav tako je vredno pojasniti, da to ni težava s specifično ključno besedo, temveč s semantiko poizvedbe. Obstaja več sintaks, ki so enake po svoji problematični naravi:

  • Ključna beseda offset je, kot je bilo omenjeno prej.
  • Konstrukcija dveh ključnih besed limit [offset] (čeprav omejitev sama po sebi ni tako slaba).
  • Filtriranje po spodnjih mejah na podlagi oštevilčenja vrstic (na primer row_number(), rownum itd.).

Vsi ti izrazi vam preprosto povedo, koliko vrstic morate preskočiti, brez dodatnih informacij ali konteksta.

V nadaljevanju tega članka je ključna beseda offset uporabljena kot povzetek vseh teh možnosti.

Življenje brez ODMORA

Zdaj pa si predstavljajmo, kakšen bi bil naš svet brez vseh teh težav. Izkazalo se je, da življenje brez zamika ni tako težko: z izbiro lahko izberete samo tiste vrstice, ki jih še nismo videli (opomba: to je tiste, ki jih ni bilo na prejšnji strani), s pogojem kje.

V tem primeru izhajamo iz dejstva, da se izbire izvajajo na urejenem nizu (dobri stari order by). Ker imamo urejen niz, lahko s precej preprostim filtrom pridobimo samo podatke, ki so za zadnjim zapisom prejšnje strani:

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

To je celotno načelo tega pristopa. Seveda postanejo stvari bolj zabavne pri razvrščanju po številnih stolpcih, a ideja je še vedno ista. Pomembno je omeniti, da je ta oblika uporabna za mnoge NoSQL- odločitve.

Ta pristop se imenuje metoda iskanja ali paginacija nabora ključev. Rešuje problem plavajočega rezultata (opomba: prej opisana situacija s pisanjem med branji strani) in seveda, kar nam je vsem všeč, deluje hitreje in stabilneje kot klasični offset. Stabilnost je v tem, da se čas obdelave zahteve ne povečuje sorazmerno s številom zahtevane tabele (opomba: če želite izvedeti več o delovanju različnih pristopov k paginaciji, lahko poglej avtorjevo predstavitev. Tam lahko najdete tudi primerjalna merila za različne metode).

Eden od diapozitivov govori o temda paginacija po ključih seveda ni vsemogočna - ima svoje omejitve. Najpomembnejše je, da nima zmožnosti branja naključnih strani (opomba: nedosledno). Vendar v dobi neskončnega drsenja (opomba: na sprednji strani) to ni taka težava. Določanje številke strani za klikanje je tako ali tako slaba odločitev pri oblikovanju uporabniškega vmesnika (opomba: mnenje avtorja članka).

Kaj pa orodja?

Paginacija na ključih pogosto ni primerna zaradi pomanjkanja instrumentalne podpore za to metodo. Večina razvojnih orodij, vključno z različnimi ogrodji, vam ne omogoča, da natančno izberete, kako se bo izvajalo paginiranje.

Situacijo otežuje dejstvo, da opisana metoda zahteva podporo od konca do konca v uporabljenih tehnologijah - od DBMS do izvajanja zahteve AJAX v brskalniku z neskončnim drsenjem. Namesto da podate samo številko strani, morate zdaj podati nabor ključev za vse strani hkrati.

Vendar pa število ogrodij, ki podpirajo paginacijo na ključih, postopoma narašča. To je tisto, kar imamo trenutno:

(Opomba: nekatere povezave so bile odstranjene zaradi dejstva, da v času prevoda nekatere knjižnice niso bile posodobljene od leta 2017-2018. Če vas zanima, si lahko ogledate izvirni vir.)

V tem trenutku je potrebna vaša pomoč. Če razvijate ali podpirate ogrodje, ki na kakršen koli način uporablja paginacijo, vas prosim, pozivam, rotim, da zagotovite izvorno podporo za paginacijo na ključih. Če imate vprašanja ali potrebujete pomoč, vam bom z veseljem pomagal (forum, Twitter, Kontaktni obrazec) (opomba: iz izkušenj z Marcusom lahko rečem, da je resnično navdušen nad širjenjem te teme).

Če uporabljate že pripravljene rešitve, za katere menite, da so vredne podpore za ostranjevanje po ključih, ustvarite zahtevo ali celo ponudite že pripravljeno rešitev, če je mogoče. Lahko se tudi povežete s tem člankom.

Zaključek

Razlog, zakaj tako preprost in uporaben pristop, kot je paginacija po ključih, ni tako razširjen, ni v tem, da bi bil tehnično težko izvedljiv ali da zahteva veliko truda. Glavni razlog je, da so mnogi navajeni videti in delati z ofsetom - ta pristop narekuje sam standard.

Posledično malo ljudi razmišlja o spremembi pristopa k paginaciji in zaradi tega se instrumentalna podpora iz ogrodij in knjižnic slabo razvija. Zato, če sta vam ideja in cilj brezpostranskega označevanja blizu, jo pomagajte širiti!

Vir: https://use-the-index-luke.com/no-offset
Avtor: Markus Winand

Vir: www.habr.com

Dodaj komentar