Bakit kailangan mo ng instrumental na suporta para sa pagination sa mga key?

Kamusta kayong lahat! Isa akong backend developer na nagsusulat ng mga microservice sa Java + Spring. Nagtatrabaho ako sa isa sa mga internal product development team sa Tinkoff.

Bakit kailangan mo ng instrumental na suporta para sa pagination sa mga key?

Sa aming koponan, ang tanong ng pag-optimize ng mga query sa isang DBMS ay madalas na lumitaw. Gusto mong maging mas mabilis nang kaunti, ngunit hindi ka palaging makakapagpatuloy sa mga index na pinag-isipang mabuti—kailangan mong maghanap ng ilang mga solusyon. Sa panahon ng isa sa mga paglibot na ito sa web sa paghahanap ng mga makatwirang pag-optimize kapag nagtatrabaho sa mga database, nakita ko Ang walang katapusang nakakatulong na blog ni Marcus Wynand, may-akda ng SQL Performance Explained. Ito ang bihirang uri ng blog kung saan maaari mong basahin ang lahat ng mga artikulo sa isang hilera.

Nais kong isalin ang isang maikling artikulo ni Marcus para sa iyo. Maaari itong tawagin sa ilang lawak na isang manifesto na naglalayong maakit ang pansin sa luma, ngunit may kaugnayan pa ring problema sa pagganap ng offset na operasyon ayon sa pamantayan ng SQL.

Sa ilang mga lugar ay pupunan ko ang may-akda ng mga paliwanag at komento. Ire-refer ko ang lahat ng naturang lugar bilang "approx." para mas malinaw

Isang maliit na pagpapakilala

Sa palagay ko alam ng maraming tao kung gaano problema at mabagal ang pagtatrabaho sa mga pinipili ng page sa pamamagitan ng offset. Alam mo ba na madali itong mapalitan ng mas mahusay na disenyo?

Kaya, sinasabi ng offset na keyword sa database na laktawan ang unang n mga tala sa kahilingan. Gayunpaman, kailangan pa ring basahin ng database ang mga unang n record na ito mula sa disk, sa ibinigay na pagkakasunud-sunod (tandaan: ilapat ang pag-uuri kung ito ay tinukoy), at pagkatapos ay posible na ibalik ang mga tala mula sa n+1 pataas. Ang pinaka-kagiliw-giliw na bagay ay ang problema ay wala sa tiyak na pagpapatupad sa DBMS, ngunit sa orihinal na kahulugan ayon sa pamantayan:

…ang mga hilera ay unang pinagbukud-bukod ayon sa at pagkatapos ay nililimitahan sa pamamagitan ng pag-drop sa bilang ng mga hilera na tinukoy sa mula sa simula...
-SQL:2016, Part 2, 4.15.3 Derived tables (tandaan: kasalukuyang pinaka ginagamit na standard)

Ang pangunahing punto dito ay ang offset ay tumatagal ng isang parameter - ang bilang ng mga talaan na lalaktawan, at iyon na. Kasunod ng kahulugang ito, makukuha lamang ng DBMS ang lahat ng mga tala at pagkatapos ay itapon ang mga hindi kailangan. Malinaw, pinipilit tayo ng kahulugang ito ng offset na gumawa ng karagdagang trabaho. At hindi mahalaga kung ito ay SQL o NoSQL.

Konting sakit na lang

Ang mga problema sa offset ay hindi nagtatapos doon, at narito kung bakit. Kung, sa pagitan ng pagbabasa ng dalawang pahina ng data mula sa disk, isa pang operasyon ang nagpasok ng bagong tala, ano ang mangyayari sa kasong ito?

Bakit kailangan mo ng instrumental na suporta para sa pagination sa mga key?

Kapag ginamit ang offset upang laktawan ang mga tala mula sa mga nakaraang pahina, sa sitwasyon ng pagdaragdag ng bagong tala sa pagitan ng mga nabasa ng iba't ibang mga pahina, malamang na makakakuha ka ng mga duplicate (tandaan: posible ito kapag binasa namin ang bawat pahina gamit ang pagkakasunud-sunod ayon sa construct, pagkatapos sa gitna ng aming output ay maaaring makakuha ng bagong entry).

Malinaw na inilalarawan ng figure ang sitwasyong ito. Binabasa ng base ang unang 10 talaan, pagkatapos nito ay ipinasok ang isang bagong tala, na nag-offset sa lahat ng nabasang talaan ng 1. Pagkatapos ay kukuha ang base ng bagong pahina mula sa susunod na 10 talaan at hindi magsisimula sa ika-11, gaya ng nararapat, ngunit mula sa Ika-10, pagdodoble ng record na ito. Mayroong iba pang mga anomalya na nauugnay sa paggamit ng expression na ito, ngunit ito ang pinakakaraniwan.

Tulad ng nalaman na natin, hindi ito mga problema ng isang partikular na DBMS o ng kanilang mga pagpapatupad. Ang problema ay sa pagtukoy ng pagination ayon sa pamantayan ng SQL. Sinasabi namin sa DBMS kung aling pahina ang kukunin o kung gaano karaming mga tala ang lalaktawan. Ang database ay simpleng hindi na-optimize ang naturang kahilingan, dahil napakakaunting impormasyon para dito.

Nararapat ding linawin na hindi ito problema sa isang partikular na keyword, ngunit sa mga semantika ng query. Mayroong ilang higit pang mga syntax na magkapareho sa kanilang likas na problema:

  • Ang offset na keyword ay tulad ng nabanggit kanina.
  • Isang pagbuo ng dalawang keyword na limitasyon [offset] (bagaman ang limitasyon mismo ay hindi masyadong masama).
  • Pag-filter ayon sa lower bounds, batay sa row numbering (halimbawa, row_number(), rownum, atbp.).

Sinasabi lang sa iyo ng lahat ng expression na ito kung ilang linya ang lalaktawan, walang karagdagang impormasyon o konteksto.

Sa ibang pagkakataon sa artikulong ito, ang offset na keyword ay ginagamit bilang isang buod ng lahat ng mga opsyong ito.

Buhay na walang OFFSET

Ngayon isipin natin kung ano ang magiging hitsura ng ating mundo kung wala ang lahat ng mga problemang ito. Lumalabas na ang buhay na walang offset ay hindi napakahirap: sa isang pili, maaari mo lamang piliin ang mga hilera na hindi pa natin nakikita (tandaan: iyon ay, ang mga wala sa nakaraang pahina), gamit ang isang kundisyon kung saan.

Sa kasong ito, magsisimula kami mula sa katotohanan na ang mga pinipili ay isinasagawa sa isang nakaayos na hanay (magandang lumang pagkakasunud-sunod ni). Dahil mayroon kaming nakaayos na hanay, maaari kaming gumamit ng medyo simpleng filter upang makuha lamang ang data na nasa likod ng huling tala ng nakaraang pahina:

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

Iyan ang buong prinsipyo ng diskarteng ito. Siyempre, nagiging mas masaya ang mga bagay kapag nag-uuri ayon sa maraming column, ngunit pareho pa rin ang ideya. Mahalagang tandaan na ang disenyo na ito ay naaangkop sa marami NoSQL-mga desisyon.

Ang pamamaraang ito ay tinatawag na paraan ng paghahanap o keyset pagination. Nilulutas nito ang problema sa lumulutang na resulta (tandaan: ang sitwasyon sa pagsusulat sa pagitan ng mga nabasang pahina na inilarawan sa itaas) at, siyempre, kung ano ang gusto nating lahat, ito ay gumagana nang mas mabilis at mas matatag kaysa sa klasikong offset. Ang katatagan ay nakasalalay sa katotohanan na ang oras ng pagproseso ng kahilingan ay hindi tumataas sa proporsyon sa bilang ng hiniling na talahanayan (tandaan: kung gusto mong matuto nang higit pa tungkol sa gawain ng iba't ibang mga diskarte sa pagination, maaari mong tingnan ang presentasyon ng may-akda. Makakahanap ka rin ng mga comparative benchmark para sa iba't ibang pamamaraan doon).

Isa sa mga slide pinag-uusapan iyonna ang pagination sa pamamagitan ng mga susi, siyempre, ay hindi makapangyarihan - mayroon itong mga limitasyon. Ang pinakamahalaga ay wala siyang kakayahang magbasa ng mga random na pahina (tandaan: hindi pare-pareho). Gayunpaman, sa panahon ng walang katapusang pag-scroll (tandaan: sa front end), hindi ito ganoong problema. Ang pagtukoy ng numero ng pahina para sa pag-click ay isang masamang desisyon sa disenyo ng UI pa rin (tandaan: opinyon ng may-akda ng artikulo).

Paano naman ang mga gamit?

Ang pagbilang ng pahina sa mga susi ay kadalasang hindi angkop dahil sa kakulangan ng instrumental na suporta para sa pamamaraang ito. Karamihan sa mga tool sa pag-unlad, kabilang ang iba't ibang mga balangkas, ay hindi nagpapahintulot sa iyo na piliin nang eksakto kung paano isasagawa ang pagination.

Ang sitwasyon ay pinalala ng katotohanan na ang inilarawan na pamamaraan ay nangangailangan ng end-to-end na suporta sa mga teknolohiyang ginamit - mula sa DBMS hanggang sa pagpapatupad ng isang kahilingan sa AJAX sa browser na may walang katapusang pag-scroll. Sa halip na tukuyin lamang ang numero ng pahina, kailangan mo na ngayong tumukoy ng isang hanay ng mga susi para sa lahat ng mga pahina nang sabay-sabay.

Gayunpaman, ang bilang ng mga framework na sumusuporta sa pagination sa mga key ay unti-unting lumalaki. Narito ang mayroon tayo sa ngayon:

(Tandaan: ang ilang mga link ay inalis dahil sa katotohanan na sa panahon ng pagsasalin ang ilang mga aklatan ay hindi na-update mula noong 2017-2018. Kung ikaw ay interesado, maaari mong tingnan ang orihinal na pinagmulan.)

Sa sandaling ito kailangan ang iyong tulong. Kung bumuo ka o sumusuporta sa isang balangkas na gumagawa ng anumang paggamit ng pagination, hinihiling ko, hinihimok ko, nakikiusap ako sa iyo na magbigay ng katutubong suporta para sa pagination sa mga susi. Kung mayroon kang mga tanong o kailangan mo ng tulong, ikalulugod kong tumulong (ang forum, kaba, contact form) (note: from my experience with Marcus, I can say na enthusiastic talaga siya sa pagkalat ng topic na ito).

Kung gumagamit ka ng mga handa na solusyon na sa tingin mo ay karapat-dapat na magkaroon ng suporta para sa pagination sa pamamagitan ng mga susi, lumikha ng isang kahilingan o kahit na mag-alok ng isang handa na solusyon, kung maaari. Maaari ka ring mag-link sa artikulong ito.

Konklusyon

Ang dahilan kung bakit ang isang simple at kapaki-pakinabang na diskarte bilang pagination sa pamamagitan ng mga susi ay hindi laganap dahil ito ay mahirap na ipatupad sa teknikal o nangangailangan ng anumang mahusay na pagsisikap. Ang pangunahing dahilan ay marami ang nakasanayan na makita at magtrabaho kasama ang offset - ang diskarte na ito ay idinidikta ng pamantayan mismo.

Bilang resulta, kakaunti ang nag-iisip tungkol sa pagbabago ng diskarte sa pagination, at dahil dito, hindi maganda ang pag-unlad ng instrumental na suporta mula sa mga frameworks at library. Samakatuwid, kung ang ideya at layunin ng offset-free pagination ay malapit sa iyo, tumulong sa pagpapalaganap nito!

Pinagmulan: https://use-the-index-luke.com/no-offset
May-akda: Markus Winand

Pinagmulan: www.habr.com

Magdagdag ng komento