Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum

Þeir dagar eru liðnir þegar þú þurftir ekki að hafa áhyggjur af því að hámarka afköst gagnagrunnsins. Tíminn stendur ekki í stað. Sérhver nýr tæknifrumkvöðull vill búa til næsta Facebook, á meðan hann reynir að safna öllum þeim gögnum sem þeir geta komist yfir. Fyrirtæki þurfa þessi gögn til að þjálfa betur líkön sem hjálpa þeim að græða peninga. Við slíkar aðstæður þurfa forritarar að búa til API sem gera þeim kleift að vinna hratt og örugglega með mikið magn upplýsinga.

Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum

Ef þú hefur verið að hanna bakenda forrita eða gagnagrunna í langan tíma, hefur þú líklega skrifað kóða til að keyra blaðsíðusettar fyrirspurnir. Til dæmis, svona:

SELECT * FROM table_name LIMIT 10 OFFSET 40

Hvernig það er?

En ef þetta er hvernig þú gerðir blaðsíðugerðina þína, þá þykir mér miður að þú gerðir það ekki á sem hagkvæmastan hátt.

Viltu mótmæla mér? Þú getur ekki eyða tími. Slaki, Shopify и Mixmax Þeir eru nú þegar að nota tæknina sem ég vil tala um í dag.

Nefndu að minnsta kosti einn bakenda þróunaraðila sem hefur aldrei notað OFFSET и LIMIT til að framkvæma blaðsíðusettar fyrirspurnir. Í MVP (Minimum Viable Product) og í verkefnum þar sem lítið magn af gögnum er notað á þessi nálgun vel við. Það „virkar bara,“ ef svo má segja.

En ef þú þarft að búa til áreiðanleg og skilvirk kerfi frá grunni, ættir þú að gæta þess fyrirfram um skilvirkni þess að spyrjast fyrir um gagnagrunna sem notaðir eru í slíkum kerfum.

Í dag munum við tala um vandamálin við algengar (of slæmar) útfærslur á síðuskipuðum fyrirspurnarvélum og hvernig á að ná háum árangri þegar slíkar fyrirspurnir eru framkvæmdar.

Hvað er athugavert við OFFSET og LIMIT?

Eins og áður sagði, OFFSET и LIMIT Þeir standa sig vel í verkefnum sem þurfa ekki að vinna með mikið magn af gögnum.

Vandamálið kemur upp þegar gagnagrunnurinn stækkar í slíka stærð að hann passar ekki lengur í minni þjónsins. Hins vegar, þegar þú vinnur með þennan gagnagrunn þarftu að nota blaðsíðusettar fyrirspurnir.

Til að þetta vandamál komi fram þarf að vera til staðar þar sem DBMS grípur til óhagkvæmrar fullrar töfluskönnunaraðgerðar við hverja blaðsíðusíðu (á meðan innsetningar- og eyðingaraðgerðir geta átt sér stað og við þurfum ekki gamaldags gögn!).

Что такое «полное сканирование таблицы» (или «последовательный просмотр таблицы», Sequential Scan)? Это — операция, в ходе которой СУБД последовательно считывает каждую строку таблицы, то есть — содержащиеся в ней данные, и проверяет их на соответствие заданному условию. Известно, что этот тип сканирования таблиц является самым медленным. Дело в том, что при его выполнении выполняется много операций ввода/вывода, задействующих дисковую подсистему сервера. Ситуацию ухудшают задержки, сопутствующие работе с данными, хранящимися на дисках, и то, что передача данных с диска в память — это ресурсоёмкая операция.

Til dæmis, þú ert með skrár yfir 100000000 notendur og þú keyrir fyrirspurn með smíði OFFSET 50000000. Þetta þýðir að DBMS verður að hlaða öllum þessum færslum (og við þurfum ekki einu sinni á þeim!), setja þær í minni og eftir það taka til dæmis 20 niðurstöður sem tilkynntar eru í LIMIT.

Segjum að það gæti litið svona út: "velja línur frá 50000 til 50020 frá 100000". Það er, kerfið mun fyrst þurfa að hlaða 50000 línum til að ljúka fyrirspurninni. Sérðu hversu mikla óþarfa vinnu hún mun þurfa að vinna?

Ef þú trúir mér ekki skaltu skoða dæmið sem ég bjó til með því að nota eiginleikana db-fiddle.com

Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum
Dæmi á db-fiddle.com

Þar, til vinstri, á sviði Schema SQL, það er kóði sem setur 100000 línur inn í gagnagrunninn og til hægri í reitinn Query SQL, tvær fyrirspurnir eru sýndar. Sú fyrsta, hægfara, lítur svona út:

SELECT *
FROM `docs`
LIMIT 10 OFFSET 85000;

Og annað, sem er áhrifarík lausn á sama vandamáli, er svona:

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

Til að uppfylla þessar beiðnir, smelltu bara á hnappinn Run efst á síðunni. Eftir að hafa gert þetta berum við saman upplýsingar um framkvæmdartíma fyrirspurnar. Það kemur í ljós að það tekur að minnsta kosti 30 sinnum lengri tíma að keyra árangurslausa fyrirspurn en að keyra þá seinni (þessi tími er breytilegur frá keyrslu til keyrslu; til dæmis gæti kerfið tilkynnt að fyrri fyrirspurnin hafi tekið 37 ms að klára, en framkvæmdin á sekúndu - 1 ms).

Og ef það eru fleiri gögn, þá mun allt líta enn verra út (til að vera sannfærður um þetta, skoðaðu mína Dæmi með 10 milljón línum).

Það sem við erum nýbúin að ræða ætti að gefa þér innsýn í hvernig gagnagrunnsfyrirspurnir eru í raun unnar.

Vinsamlegast athugaðu að því hærra sem gildið er OFFSET — því lengri tíma tekur að ljúka beiðninni.

Hvað ætti ég að nota í stað samsetningar OFFSET og LIMIT?

Í stað samsetningar OFFSET и LIMIT Það er þess virði að nota uppbyggingu sem byggt er samkvæmt eftirfarandi kerfi:

SELECT * FROM table_name WHERE id > 10 LIMIT 20

Þetta er framkvæmd fyrirspurnar með blaðsíðugerð sem byggir á bendili.

Í stað þess að geyma núverandi á staðnum OFFSET и LIMIT og senda þær með hverri beiðni, þú þarft að geyma síðasta móttekna aðallykil (venjulega er þetta ID) Og LIMIT, fyrir vikið verða fyrirspurnir svipaðar ofangreindum fengnar.

Hvers vegna? Málið er að með því að tilgreina sérstaklega auðkenni síðustu línu sem lesið var, segirðu DBMS þínum hvar það þarf að byrja að leita að nauðsynlegum gögnum. Þar að auki mun leitin, þökk sé notkun lykilsins, fara fram á skilvirkan hátt; kerfið þarf ekki að vera truflað af línum utan tilgreinds sviðs.

Við skulum skoða eftirfarandi árangurssamanburð á ýmsum fyrirspurnum. Hér er árangurslaus fyrirspurn.

Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum
Hæg beiðni

Og hér er fínstillt útgáfa af þessari beiðni.

Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum
Fljótleg beiðni

Báðar fyrirspurnirnar skila nákvæmlega sama magni af gögnum. En það fyrsta tekur 12,80 sekúndur að klára og það síðara tekur 0,01 sekúndu. Finnst þér munurinn?

Möguleg vandamál

Til að fyrirhuguð fyrirspurnaraðferð virki á skilvirkan hátt verður taflan að hafa dálk (eða dálka) sem inniheldur einstaka, raðgreinar, eins og heiltöluauðkenni. Í sumum sérstökum tilfellum getur þetta ráðið úrslitum um árangur þess að nota slíkar fyrirspurnir til að auka hraða vinnu með gagnagrunninn.

Естественно, конструируя запросы, нужно учитывать особенности архитектуры таблиц, и выбирать те механизмы, которые наилучшим образом покажут себя на имеющихся таблицах. Например, если нужно работать в запросах с большими объёмами связанных данных, вам может показаться интересной þetta grein.

Ef við stöndum frammi fyrir því vandamáli að missa af aðallykil, til dæmis ef við erum með töflu með mörgum-til-mörgum tengslum, þá er hefðbundin nálgun að nota OFFSET и LIMIT, er tryggt að henta okkur. En notkun þess getur leitt til hugsanlegra hægra fyrirspurna. Í slíkum tilfellum myndi ég mæla með því að nota sjálfvirkan stækkandi aðallykil, jafnvel þótt hann sé aðeins nauðsynlegur til að meðhöndla blaðsíðusettar fyrirspurnir.

Ef þú hefur áhuga á þessu efni - hér, hér и hér - nokkur gagnleg efni.

Niðurstöður

Meginniðurstaðan sem við getum dregið er sú að, ​​sama hvaða stærð gagnagrunna við erum að tala um, þá er alltaf nauðsynlegt að greina hraða framkvæmdar fyrirspurnar. Nú á dögum er sveigjanleiki lausna gríðarlega mikilvægur og ef allt er hannað rétt frá upphafi vinnu við ákveðið kerfi getur þetta í framtíðinni bjargað þróunaraðilanum frá mörgum vandamálum.

Hvernig greinir þú og fínstillir gagnagrunnsfyrirspurnir?

Forðastu að nota OFFSET og LIMIT í blaðsíðusettum fyrirspurnum

Heimild: www.habr.com

Bæta við athugasemd