Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral

Aeg on möödas, kus ei pidanud muretsema andmebaaside jĂ”udluse optimeerimise ĂŒle. Aeg ei seisa paigal. Iga uus tehnoloogiatehnoloogia Ă€rimees soovib luua jĂ€rgmist Facebooki, pĂŒĂŒdes samal ajal koguda kĂ”iki andmeid, millele nad ligi pÀÀsevad. Need andmed on ettevĂ”ttele vajalikud kvaliteetsemate mudelite Ă”petamiseks, mis aitavad kasumit teenida. Sellistes tingimustes peavad arendajad looma selliseid API-sid, mis vĂ”imaldavad kiiresti ja usaldusvÀÀrselt töötada hiiglaslike andmemahtudega.

Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral

Kui olete juba mĂ”nda aega tegelenud rakenduste serveriplokkide vĂ”i andmebaaside projekteerimisega, olete tĂ”enĂ€oliselt kirjutanud koodi lehekĂŒljepĂ”histe pĂ€ringute tĂ€itmiseks. NĂ€iteks selline:

SELECT * FROM table_name LIMIT 10 OFFSET 40

Kas tÔesti?

Kuid kui te tegite lehekĂŒljepĂ”hise jagamise just nii, siis pean kurbusega mĂ€rkima, et tegite seda kaugel mitte kĂ”ige tĂ”husamal viisil.

Kas soovite mul vastu vaielda? Saate ei kulutama aega. Slack, Shopify ja Mixmax juba kasutavad tehnikaid, millest ma tÀna rÀÀkida tahan.

Nimetage vĂ€hemalt ĂŒks taustaarendaja, kes pole kunagi kasutanud CHECKSUM_AGG ja LIMIT lehekĂŒljepĂ”histe pĂ€ringute tĂ€itmiseks. MVP (Minimum Viable Product, minimaalne elujĂ”uline toode) ja projektides, kus kasutatakse vĂ€ikseid andmemahte, on see lĂ€henemine tĂ€iesti rakendatav. See, nii öelda, "lihtsalt töötab".

Kuid kui on vaja nullist luua usaldusvÀÀrseid ja tĂ”husaid sĂŒsteeme, tuleb eelnevalt hoolitseda andmebaaside pĂ€ringute tĂ”hususe eest, mida sellistes sĂŒsteemides kasutatakse.

TĂ€na rÀÀgime probleemidest, mis on seotud laialdaselt kasutatavate (kahjuks) lehekĂŒljepĂ”histe pĂ€ringumehanismidega, ja kuidas saavutada kĂ”rget jĂ”udlust selliste pĂ€ringute tĂ€itmisel.

Mis on valesti OFFSETi ja LIMITiga?

Kuidas juba mainitud, CHECKSUM_AGG ja LIMIT nÀitavad end vÀga hÀsti projektides, kus ei ole vaja töötada suurte andmemahutega.

Probleem tekib siis, kui andmebaas kasvab nii suureks, et see ei mahu enam serveri mĂ€llu. Kuid samal ajal tuleb sellise andmebaasiga töötamisel kasutada lehekĂŒljepĂ”hiseid pĂ€ringuid.

Probleemi ilmenemiseks peab olema olukord, kus andmebaas kasutab iga pĂ€ringu tĂ€itmiseks ebaefektiivset tĂ€ielikku tabeli skaneerimist (Full Table Scan) lehekĂŒljed jagades (samal ajal vĂ”ivad toimuda andmete sisestamis- ja kustutamisoperatsioonid ning me ei vaja aegunud andmeid!).

Mis on "tĂ€ielik tabeli skaneerimine" (vĂ”i "jĂ€rjestikune tabeli vaatamine", Sequential Scan)? See on operatsioon, mille kĂ€igus andmebaas loeb jĂ€rjestikku iga tabeli rida, st sisaldatud andmeid, ja kontrollib neid antud tingimusele vastavuse suhtes. On teada, et see tĂŒĂŒp tabeli skaneerimist on aeglasem. Selle pĂ”hjuseks on see, et selle tĂ€itmise kĂ€igus toimub palju sisend-/vĂ€ljundoperatsioone, mis hĂ”lmavad serveri kettasĂŒsteemi. Seisundit halvendavad viivitused, mis kaasnevad kettal hoitud andmete töötlemisega, ja see, et andmete edastamine kettalt mĂ€llu on ressursimahukas operatsioon.

NÀiteks, teil on kirjed 100000000 kasutajast ja teete pÀringu koos konstruktsiooniga OFFSET 50000000. See tÀhendab, et andmebaas peab laadima kÔik need kirjed (ja need ei ole meile isegi vajalikud!), pannakse need mÀllu ja seejÀrel, oletame, vÔtab 20 tulemust, millest on teavitatud LIMIT.

Öeldes, et see vĂ”iks vĂ€lja nĂ€ha nii: "valige read 50000 kuni 50020 100000-st". See tĂ€hendab, et sĂŒsteem peab pĂ€ringu tĂ€itmiseks esmalt laadima 50000 rida. NĂ€ete, kui palju tarbetut tööd tal tuleb teha?

Kui ei usu — vaadake nĂ€idet, mille ma lĂ”in, kasutades vĂ”imalusi db-fiddle.com. 

Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral
NĂ€idis db-fiddle.com-is

Seal, vasakul, valdkonnas Schema SQL, on kood, mis sisestab andmebaasi 100000 rida, ja paremal, valdkonnas Query SQL, on nÀidatud kaks pÀringut. Esimene, aeglane, nÀeb vÀlja nii:

SELECT *
FROM `docs`
LIMIT 10 OFFSET 85000;

Ja teine, mis on sama probleemi efektiivne lahendus, on nii:

SELECT *
FROM `docs`
WHERE id > 85000
LIMIT 10;

Nende pĂ€ringute tĂ€itmiseks piisab, kui vajutada nuppu KĂ€ita lehe ĂŒlaosas. Kui te seda teete, saame vĂ”rrelda pĂ€ringute tĂ€itmise aega. Selgub, et ebaefektiivse pĂ€ringu tĂ€itmiseks kulub vĂ€hemalt 30 korda rohkem aega kui teise (kĂ€ivituse vahel vĂ”ib see aeg varieeruda, nĂ€iteks sĂŒsteem vĂ”ib teatada, et esimese pĂ€ringu tĂ€itmine kestis 37 ms, samas kui teise oma - 1 ms).

Ja kui andmeid on rohkem, siis nÀeb see veel hullem vÀlja (selle kinnitamiseks vaadake minu nÀide 10 miljoni reaga).

See, millest me just rÀÀkisime, peaks andma teile arusaamise, kuidas pÀringud tegelikult andmebaasidesse jÔuavad.

Pidage meeles, et mida suurem on vÀÀrtus CHECKSUM_AGG seda kauem pÀring kestab.

Mida peaks kasutama OFFSET-i ja LIMIT-i kombinatsiooni asemel?

OFFSET-i ja LIMIT-i kombinatsiooni asemel CHECKSUM_AGG ja LIMIT on parem kasutada konstruktsiooni jÀrgmisel viisil:

SELECT * FROM table_name WHERE id > 10 LIMIT 20

See on pÀringu tÀitmine, mis pÔhineb lehejaotusel (Cursor based pagination).

Ahnem kusagil kohapeal hoida praeguseid CHECKSUM_AGG ja LIMIT ja edastada neid iga pÀringuga, peaksite hoidma viimasena saadud peavÔtit (tavaliselt on see ID) ja LIMIT, mis viib selleni, et pÀringud sarnanevad eespool toodud nÀiteks.

Miks? Asi on selles, et kui te nĂ€itate selgesĂ”naliselt viidatud viimase ridade identifikaatorit, anname oma andmebaasihaldus sĂŒsteemile teada, kust alustada vajalike andmete otsimist. Ja see otsing, kasutades vĂ”tit, toimub tĂ”husalt, sĂŒsteem ei pea kĂ”rvalistele ridadele tĂ€helepanu pöörama, mis jÀÀvad mÀÀratud vahemikust vĂ€lja.

Vaadakem jÀrgmisi erinevate pÀringute jÔudluse vÔrdlusi. Siin on ebaefektiivne pÀring.

Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral
Aeglane pÀring

Aga siin on selle pÀringu optimeeritud versioon.

Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral
Kiire pÀring

MÔlemad pÀringud tagastavad tÀpselt sama hulga andmeid. Kuid esimese tÀitmine kestab 12,80 sekundit, samas kui teisel vaid 0,01 sekundit. Kas mÀrkate vahet?

VÔimalikud probleemid

Ettepaneku meetodi tÔhusaks toimimiseks peab tabelis olema veerg (vÔi veerud), mis sisaldavad ainulaadseid, jÀrjestikuseid indekse, nÀiteks tÀisarvulist identifikaatorit. MÔnedes spetsiifilistes olukordades vÔib see mÀÀrata taoliste pÀringute kasutamise edu andmebaasi töö kiirusel.

Muidugi tuleb pÀringute koostamisel arvesse vÔtta tabelite arhitektuuri eripÀra ja valida need mehhanismid, mis toovad parima tulemuse olemasolevates tabelites. NÀiteks, kui peate töötama suurte seotud andmahulkadega pÀringutes, vÔib teile huvi pakkuda see artikkel.

Kui seisame silmitsi esmase vĂ”tme puudumise probleemiga, nĂ€iteks kui tabelis on "palju-palju" suhe, siis traditsiooniline lĂ€henemine, mis hĂ”lmab CHECKSUM_AGG ja LIMIT, sobib meile kindlasti. Kuid selle rakendamine vĂ”ib viia potentsiaalselt aeglaste pĂ€ringute tĂ€itmiseni. Niisugustes olukordades soovitaksin kasutada automaatse suurenemisega esmase vĂ”tit, isegi kui see on vajalik ainult pĂ€ringute lehekĂŒntede kaupa tĂ€itmiseks.

Kui see teema teid huvitab — siin on, siin on ja siin on — mĂ”ned kasulikud materjalid.

Summary

Peamine jĂ€reldus, mille vĂ”ime teha, on see, et olenemata andmebaaside suurusest, tuleb alati analĂŒĂŒsida pĂ€ringute tĂ€itmise kiirus. TĂ€napĂ€eval on lahenduste skaleeritavus ĂŒlioluline, ning kui juba sĂŒsteemi tööplaneerimise alguses on kĂ”ik Ă”igesti projekteeritud, vĂ”ib see edaspidi aidata arendajal kokku puutuda paljude probleemidega.

Kuidas te analĂŒĂŒsite ja optimeerite andmebaaside pĂ€ringuid?

Ärge kasutage kĂŒsitlustes OFFSET ja LIMIT lehekĂŒlgede jagamise korral

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster