Need pĂ€evad on möödas, mil ei olnud vaja andmebaaside jĂ”udluse optimeerimise pĂ€rast muretseda. Aeg ei seisa paigal. Iga uus tehnoloogiaettevĂ”tja soovib luua jĂ€rgmist Facebooki, pĂŒĂŒdledes samas koguda kĂ”iki andmeid, mis on nende kĂ€eulatuses. Need andmed on ettevĂ”tetele vajalikud, et paremini koolitada mudeleid, mis aitavad raha teenida. Sellistes tingimustes peavad arendajad looma selliseid API-sid, mis vĂ”imaldavad kiiresti ja usaldusvÀÀrselt töötada tohutute andmemahtudega.
Kui olete mĂ”nda aega tegelenud rakenduste vĂ”i andmebaaside serveripoolsete osade projekteerimisega, siis olete tĂ”enĂ€oliselt kirjutanud koodi lehe jagamise pĂ€ringute tĂ€itmiseks. NĂ€iteks â sellise:
SELECT * FROM table_name LIMIT 10 OFFSET 40
Kas see on tÔsi?
Kuid kui te olete lehe jagamist teinud just nii, pean kahetsema, et olete seda teinud kaugel kÔige tÔhusamal viisil.
Kas soovite mulle vastu vaielda? . , ja kasutavad juba tehnikaid, millest ma tÀna rÀÀkida tahan.
Nimetage vĂ€hemalt ĂŒks tagapoolt arendaja, kes pole kunagi kasutanud OFFSET ja LIMIT lehtede jagamise pĂ€ringute tĂ€itmiseks. MVP-s (Minimum Viable Product, minimaalne elujĂ”uline toode) ja projektides, kus kasutatakse vĂ€ikeseid andmemahtusid, on see lĂ€henemine tĂ€iesti rakendatav. See, nii öelda, "lihtsalt töötab".
Aga kui on vaja nullist luua usaldusvÀÀrseid ja tĂ”husaid sĂŒsteeme, tuleks ette mĂ”elda andmebaaside pĂ€ringute tĂ€itmise efektiivsusele, mida sellistes sĂŒsteemides kasutatakse.
TÀna rÀÀgime probleemidest, mis kaasnevad laialdaselt kasutatavate (kahjuks) lehtede jagamise pÀringute tÀitmise mehhanismide rakendustega, ja sellest, kuidas saavutada kÔrge jÔudlus selliste pÀringute tÀitmisel.
Mis on valesti OFFSET-i ja LIMIT-iga?
Nagu juba mainitud, OFFSET ja LIMIT nÀitavad nad end suurepÀraselt projektides, kus ei pea töötama suurte andmemahtudega.
Probleem tekib siis, kui andmebaas kasvab nii suureks, et ei mahu enam serveri mĂ€llu. Samas tuleb selle andmebaasiga töötades kasutada lehekĂŒljepĂ”hiseid pĂ€ringuid.
Selle probleemi ilmnemiseks peab tekkima olukord, kus andmebaasi haldussĂŒsteem peab iga lehekĂŒljepĂ”hise pĂ€ringu tĂ€itmisel pöörduma ebaefektiivse tĂ€istabeli skaneerimise (Full Table Scan) poole (samal ajal vĂ”ivad toimuda andmete lisamine ja kustutamine, ja vanad andmed ei ole meile vajalikud!).
Mis on "tĂ€ielik tabeli skaneerimine" (vĂ”i "jĂ€rjekorraga tabeli vaatamine", Sequential Scan)? See on toiming, mille kĂ€igus andmebaasiserver loeb jĂ€rjestikuuliselt lĂ€bi iga tabeli rea, st andmed, mis seal sisaldub, ning kontrollib neid mÀÀratud tingimuse jĂ€rgi. On teada, et see skaneerimistĂŒĂŒp on aeglaseim. Probleem on selles, et selle teostamise kĂ€igus tehakse palju sisendi/vĂ€ljundi operatsioone, mis hĂ”lmavad serveri ketasĂŒsteemi. Situatsiooni halvendavad viivitused, mis kaasnevad kettal salvestatud andmetega töötamisel, ning see, et andmete edastamine kettalt mĂ€lu on ressursimahukas toiming.
NĂ€iteks, teil on kirjed 100000000 kasutajast ja teete pĂ€ringu konstruktsiooniga OFFSET 50000000. See tĂ€hendab, et andmebaasiserver peab laadima kĂ”ik need kirjed (ja need pole ju meile isegi vajalikud!), paigutama need mĂ€lu ning seejĂ€rel vĂ”tma, ĂŒtleme, 20 tulemust, millest on teatatud LIMIT.
Oletagem, et see vĂ”ib vĂ€lja nĂ€ha nii: "vali read 50000 kuni 50020 100000-st". See tĂ€hendab, et sĂŒsteem peab pĂ€ringu tĂ€itmiseks esmalt laadima 50000 rida. Kas nĂ€ete, kui palju tarbetut tööd tal tuleb teha?
Kui te ei usu, vaadake nĂ€idet, mille ma lĂ”in vĂ”imaluste abil .Â

NĂ€ide db-fiddle.com lehelt
Vasakul, vÀljadel Schema SQL, on kood, mis sisestab andmebaasi 100000 rida, ja paremal, vÀljadel Query SQL, on esitatud kaks pÀringut. Esimene, aeglane, nÀeb vÀlja selline:
SELECT *
FROM `docs`
LIMIT 10 OFFSET 85000;
Teine, mis on tĂ”hus lahendus sama ĂŒlesande jaoks, on selline:
SELECT *
FROM `docs`
WHERE id > 85000
LIMIT 10;
Nende pĂ€ringute tĂ€itmiseks piisab, kui vajutada nuppu Run lehe ĂŒlaosas. PĂ€rast seda vĂ”rrelgem pĂ€ringute tĂ€itmise aega. Selgub, et ebaefektiivse pĂ€ringu tĂ€itmiseks kulub vĂ€hemalt 30 korda rohkem aega kui teise tĂ€itmiseks (iga kĂ€ivitamise korral vĂ”ib see aeg varieeruda, nĂ€iteks sĂŒsteem vĂ”ib teatada, et esimese pĂ€ringu tĂ€itmiseks kulus 37 ms, teine aga 1 ms).
Ja kui andmeid on rohkem, halveneb see veelgi (kui soovite selles veenduda, vaadake minu 10 miljoni realise andmestiku nÀidet).
See, mida me just arutasime, peaks andma teile mingisuguse arusaama sellest, kuidas andmebaasi pÀringud tegelikult töötavad.
Pidage meeles, et mida suurem on vÀÀrtus OFFSET â seda kauem vĂ”tab pĂ€ringu tĂ€itmine aega.
Mida kasutada kombinatsiooni OFFSET ja LIMIT asemel?
Kombinatsiooni asemel OFFSET ja LIMIT on mÔistlik kasutada jÀrgnevat struktuuri:
SELECT * FROM table_name WHERE id > 10 LIMIT 20
See on lehekestamine, mis pÔhineb kursori kasutamisel.
Selle asemel, et sĂ€ilitada praeguseid OFFSET ja LIMIT ja edastada neid iga pĂ€ringuga, tuleb salvestada viimane saadud pĂ”hivĂ”ti (tavaliselt see on ID) ja LIMIT, mille tulemusena saadakse pĂ€ringud, mis meenutavad ĂŒlaltoodud.
Miks? Asja on selles, et kui te mĂ€rkite selgelt viimase loetud rea identifikaatori, siis te annate oma andmebaasi haldustarkvarale teada, kust alustada vajalike andmete otsimist. Otsing toimub tĂ”husalt tĂ€nu vĂ”tme kasutamisele, sĂŒsteem ei pea hĂ€irima, et otsida ridu, mis jÀÀvad vĂ€ljapoole nĂ€idatud vahemikku.
Vaadakem jÀrgmisi erinevate pÀringute jÔudluse vÔrdlusi. Siin on ebaefektiivne pÀring.

Aeglane pÀring
Ja siin on selle pÀringu optimeeritud versioon.

Kiire pÀring
MÔlemad pÀringud tagastavad tÀpselt sama andmehulga. Kuid esimese tÀitmiseks kulub 12,80 sekundit, teise jaoks aga 0,01 sekundit. Tunnete erinevust?
VÔimalikud probleemid
Effektiivse pÀringute tÀitmise meetodi tagamiseks peab tabelis olema veerg (vÔi veerud), mis sisaldavad unikaalseid ja jÀrjestatud indekseid, nagu tÀisarvuline identifikaator. MÔningatel spetsiifilistel juhtudel vÔib see mÀÀrata, kas selliseid pÀringuid on vÔimalik kasutada andmebaasi töö kiirusel parandamiseks.
Loomulikult, pÀringute koostamisel tuleb arvesse vÔtta tabelite arhitektuuri eripÀra ning valida mehhanismid, mis nÀitavad end olemasolevates tabelites parimat. artiklit.
Kui seisame silmitsi primaarvĂ”tme puudumise probleemiga, nĂ€iteks kui meil on tabel, kus on "palju-palju", siis traditsiooniline lĂ€henemine, mis eeldab rakendamist OFFSET ja LIMIT, sobib meile kindlasti. Kuid selle rakendamine vĂ”ib tuua kaasa potentsiaalselt aeglaste pĂ€ringute tĂ€itmise. Sellisel juhul soovitaksin kasutada automaatselt suurenemist toetavat primaarvĂ”tit, isegi kui see on vajalik ainult lehekĂŒljel tehtavate pĂ€ringute tĂ€itmiseks.
Kui teema huvitab â , ja â mĂ”ned kasulikud materjalid.
KokkuvÔte
Peamine jĂ€reldus, mille me teha saame, on see, et olenemata andmebaasi suurusest tuleb alati analĂŒĂŒsida pĂ€ringute tĂ€itmise kiirus. TĂ€napĂ€eval on lahenduste skaleeritavus ÀÀrmiselt oluline, ja kui alustada sĂŒsteemi projekteerimist Ă”igesti, vĂ”ib see tulevikus vabastada arendaja paljusid probleemidest.
Kuidas te analĂŒĂŒsite ja optimeerite andmebaaside pĂ€ringuid?
Allikas: habr.com
