Pogoste napake, ki vodijo do problema poizvedbe N+1, se na splošno vrtijo okoli tega, kako se podatki pridobijo iz baze podatkov, še posebej pri uporabi okvirov objektnega relacijskega preslikave (ORM) ali pisanju poizvedb baze podatkov ročno. Tu so podrobna pojasnila teh napak:
** 1. Pridobivanje podatkov v ločenih poizvedbah
Glavni vzrok problema poizvedbe N+1 je strukturiranje kode, da najprej pridobi seznam zapisov z eno poizvedbo, nato pa izvede dodatno poizvedbo za vsak zapis za pridobivanje podatkov o povezanih. Na primer, poizvedovanje o seznamu uporabnikov in nato ločeno poizvedovanje po objavi za vsakega uporabniškega rezultata v 1 poizvedbo za uporabnike in n poizvedbe za objave, kjer je n število uporabnikov. To vodi do številnih majhnih poizvedb namesto ene optimizirane poizvedbe [1] [2] [3] [7].
** 2. Privzeto se zanaša na leno nalaganje
Večina ORM uporablja leno nalaganje kot privzeto strategijo pridobivanja, kar pomeni, da so povezane entitete pridobljene le, ko jih izrecno dostopate. Čeprav lahko to prihrani vire, če povezani podatki niso potrebni, povzroči, da se pri ponovitvi nad zbirkami sproži več poizvedb, kar nevede povzroči problem N+1. Na primer, dostop do avtorja vsake objave na spletnem dnevniku sproži ločeno poizvedbo na objavo [5].
** 3. Slepo ponovna uporaba poizvedb brez kontekstnih prilagoditev
Ponovna uporaba iste poizvedbe v različnih delih aplikacije brez prilagajanja lahko povzroči nepotrebno iskanje podatkov in poslabša težavo n+1. Poizvedbe, ki niso optimizirane za posebne primere uporabe, lahko pridobijo nepopolne podatke, kar spodbudi dodatne poizvedbe, da pozneje dobijo povezane informacije [8].
** 4. Ne uporabljate tehnik željnega nalaganja ali optimizacije poizvedb
Če ne uporabite željne obremenitve (pridobivanje povezanih podatkov v začetni poizvedbi) ali optimizirano povezavo, povzroči več krogov v bazo podatkov. To se zgodi, ko razvijalci ne izrecno naročijo svojega ORM ali poizvedb, da skupaj naložijo povezane entitete, kar vodi do številnih majhnih poizvedb namesto enega, učinkovitega [5] [6] [7].
** 5. Ignoriranje vpliva večkratnih krogov na bazo podatkov
Razvijalci včasih domnevajo, da so številne majhne poizvedbe hitrejše od ene zapletene poizvedbe, vendar vsaka poizvedba vključuje zakasnitev omrežja in obdelavo nad glavo. Kumulativni učinek poizvedb N+1 bistveno upočasni odzivni čas uporabe in poveča obremenitev baze podatkov, zlasti ko raste glasnost podatkov [1] [3] [5].
** 6. Pomanjkanje ozaveščenosti ali odkrivanje problema
Ker se vsaka individualna poizvedba v vzorcu N+1 izvaja hitro, se pogosto ne prikaže v dnevnikih počasnih poizvedb ali orodjih za spremljanje, zaradi česar je tihi ubijalec uspešnosti. Razvijalci morda ne bodo opazili težave, dokler se odzivnost aplikacij znatno poslabša [2] [5] [7].
Če povzamemo, problem poizvedbe N+1 nastane predvsem zaradi neučinkovitih vzorcev podatkov, ki pridobijo podatke, ki poizvedujejo povezane podatke v ločenih poizvedbah za vsak zapis, ne pa za pregledovanje ali povezovanje poizvedb. To se pogosto povzroča privzeto leno nalaganje v ORMS, neuspeh pri uporabi željnega nalaganja ali šarženja in ponovne uporabe splošnih poizvedb brez optimizacije. Rezultat je prekomerni okrogli baze podatkov, ki poslabšajo zmogljivost in razširljivost [1] [2] [3] [5] [6] [7].
Navedbe:
[1] https://planetscale.com/blog/what-is-n-1-query-problem-and-how-to-solve-it
[2] https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-Orm-Object-Relational
[3] https://www.pingcap.com/article/how-to-effiptly-solve-the-n1-query-problem/
[4] https://evnedev.com/blog/development/the-n1-query-problem-what-is-it-and-how-do-you-solve-it/
[5] https://digma.ai/n1-query-problem-and-how-to-detect-it/
[6] https://www.linkedin.com/posts/aftab-ahmed-bb002827_avoiding-the-n1-query-problem-a-common-activity-727052766297081818561-ZMZ6
[7] https://dev.to/Lovestaco/the-n1-query-problem-the-silent-performance-kkiller-2b1c
[8] https://www.okoone.com/spark/Technology-innovation/avoid-these-7-sql-ristakes-for-beter-database-management/