Kas ja millised probleemid võivad tekkida andmebaasirakenduse tegemisel kasutades mõnda ORM (Object-Relational Mappers, objekt-relatsioonvastenduse) vahendit?

Postitas Erki Eessaar 02.10.2024 13:01 (muudeti 02.10.2024 13:09)
SIIN (Sulaoja, K.M., Saarep, A. Cognate kasutajamugavuse parandamine ja arendustöö lihtsustamine) on 2024. aasta bakalaureusetöö, mille sisuks oli ühe Tallinna Tehnikaülikoolis õppetöö läbiviimist abistava süsteemi parandamine ning edasiarendamine. Ka süsteemi eelmine versioon tehti üliõpilaste poolt. Süsteemi realiseerimiseks kasutati Django ORMi. Jaotises 3.3.1 (lk 26-27) kirjutatakse ORM probleemidest ning jaotises 3.3.2 tuuakse näide, et need probleemid päriselt esinevad. ORM probleemide hulka kuulub see, et vahendi oskamatu kasutuse korral tehakse andmebaasi põhjal liiga palju päringuid ja see aeglustab süsteemi tööd. Autorid tõdesid, et süsteemi puhul "oli reageerimiskiiruse pudelikaelaks tagarakenduse kood ning Djangosse sisseehitatud objekt-relatsioonvastanduse ehk ORM-i (object-relational mapping) valekasutus".

Autorid uurisid enne paranduste tegemist rakenduse tööd 63 registreeritud projekti ning hindamissüsteemi kaheksa tähtpunkti korral. "Selgus, et 63 projekti puhul tehakse 12124 erinevat baasipäringut, mille kogupikkus jäi keskmiselt vahemikku 6400-6700ms. Sealjuures 12117 neist olid märgitud sarnasteks, millest omakorda 7862 olid duplikaadid. Kogu aeg lokaalselt, mis kulus alates päringu vastuvõtust kuni vastuse saatmiseni (Total CPU time, andmete saatmine üle võrgu ei ole sisse arvestatud), jäi vahemikku 20-22 sekundit. Tootekeskkonna kogu ajakulu oli vahemikus 12-14 sekundit".

Autorid kirjutasid rakenduse paranduste kohta: "Kõige suurema mõjuga neist oli baasipäringute viimine tsüklitest väljapoole. Varasemalt tehti tsüklites kokku mitutuhat duplikaadist baasipäringuid. Tsüklites päringute tegemine tõi esile ka jõudlust suuresti mõjutava N+1 probleemi, mis lahendati baasolemiga seotud andmete kohese baasist välja pärimisega. Lisaks üritati võimalikult palju eemaldada Django Model tüüpi objektide kasutust, kuna nende loomine on väga kulukas protsess. Selle asemel küsiti välja ning kasutati andmeid primitiivsete väärtustena. Optimeerimise tulemusena toodi baasipäringute arv alla 9-le päringule, mille tegemiseks kulus 10-14ms. Kusjuures enam ei tehta mitte ühtegi sarnast või duplikaadist baasipäringut. Lokaalselt kulub varasema 20-22 sekundi asemel päringule nüüd 140-160ms. Tootekeskkonnas aga veidi üle 300ms, mis tähendab, et päring on ligi 70 korda kiirem."

ORMis tulenevaid probleeme:
  • tabelite struktuuri kirjeldamine ORMi koodis võib viia halvasti struktureeritud andmebaasini,
  • päringute kirjeldamine ORMi koodis võib viia vigaste või ebaefektiivsete andmebaasi päringute täitmiseni,
  • suunab tegema valikuid, mis on rakenduse kiire valmimise seisukohast mugavad, kuid teises olukorras vähendab andmete kasutamise mugavust,
    • surrogaatvõtme veeru nimega id automaatne lisamine
      • kas on ikka meeles teisi võtmeid leida ja jõustada?
      • tabelite ühendamise päringute käsitsi kirjutamine on tänu sellisele nimevalikule ebamugavam.
  • oskamatu kasutus võib viia liigsete andmebaasipäringute käivitamiseni,
    • loetakse rida ühest tabelist ja siis tsüklis seotud read teisest tabelist (iga rea küsimiseks eraldi lause), selle asemel, et kõiki neid andmeid ühe lausega küsida.

Mõttearendus sellel teemal, kuidas ORM pakutav (objektorienteeritud) mõtteviis ja relatsiooniline mõtteviis on põhimõtteliselt erinevad, sest esimene nendest töötab üksikute olemitega teine aga nende hulkadega ning kuidas ORM propageeritav mõtteviis viib selleni, et andmebaasisüsteem peab tegema liigselt tööd (täitma liiga palju SQL lauseid) ning selle all kannatab süsteemi jõudlus..

ORM vahendi(te) probleemidele osutab see uuring 67 avatud lähtekoodiga tarkvara põhjal.

Siin on veel üks suure hulga põhjendustega selgitus, miks üks arendaja loobus ORMi kasutamisest ning eelistab ise SQL lauseid kirjutada.

Siin on arutelu, kus kõrvutatakse ORMi ja andmebaasiserveris talletatud rutiinidest, vaadetest ja hetktõmmistest koosneva virtuaalse andmete kihi kasutamist.

Isegi ORMi kasutamise korral saab teha nii, et  rakendus kasutab andmebaasi läbi avaliku andmebaasi liidese e virtuaalse andmete kihi. Sellisel juhul loeks rakendus andmeid vaadetest (näiteks Djangos on see võimalik) ning muudaks andmeid kasutades andmebaasiserveris talletatud rutiine (näiteks Djangos on see võimalik). Andmete kitsendustele vastavuse kontroll toimuks andmebaasi tasemel (kasutades deklaratiivseid kitsendusi ja reegleid), mitte rakenduse tasemel nagu ORM vahendid üldiselt propageerivad. Rakenduse tasemele andmete kontrolli probleemiks on:

  • üleliigsed päringud andmebaasi põhjal, mis kokkuvõttes aeglustavad ORM abil loodud programmi tööd,
  • kontrollide ebapiisavus selles mõttes, et juhul kui samu andmeid kasutab samaaegselt mitu kasutajat, siis võivad need kontrollid lasta läbi reeglitele mittevastavaid andmeid.


Kuigi eelnev näitab, et ORMi ja andmebaasi avalikku liidest saab koos kasutada, siis praktikas on need alternatiivid.

  • Alternatiiv 1: Rakendus kasutab andmebaasi läbi ORMi. ORM vahend genereerib ise SQL koodi, millega loetakse ja muudetakse andmebaasis andmeid otse baastabelites. Selleks, et piirata kasutajate juurdepääsu teatud tingimustega tabeli ridadele, pakuvad andmebaasisüsteemid vahendeid nagu turvapoliitikad (PostgreSQL) või peeneteralised juurdepääsupiirangud.
  • Alternatiiv 2: Rakendus kasutab andmebaasi läbi avaliku andmebaasi liidese, mille realiseerimiseks kasutatakse andmebaasis loodud vaateid, rutiine ja materialiseeritud vaateid e hetktõmmiseid. Rakendus ei pöördu otse baastabelite poole, vaid kasutab nendes olevaid andmeid läbi avaliku liidese.

Hinda postitust:

Keskmine hinne : Pole veel hinnanguid!