NoSQL duomenų bazių tipai ir panaudojimas

Kas yra NoSQL ir kodėl apie tai verta žinoti

Kai prieš kokius dešimt metų pradėjau dirbti su duomenų bazėmis, viskas atrodė paprasta – buvo MySQL arba PostgreSQL, ir tau to pakako. Bet technologijos vystosi, duomenų kiekiai auga eksponentiškai, o tradicinės reliacinės duomenų bazės kartais tiesiog nebespėja. Čia ir ateina į pagalbą NoSQL pasaulis.

NoSQL – tai ne viena konkreti technologija, o visas spektras duomenų bazių, kurios atsirado kaip atsakas į didėjančius poreikius. Pavadinimas gali klaidinti – tai nereiškia „ne SQL”, greičiau „ne tik SQL” (Not Only SQL). Šios duomenų bazės atsirado tada, kai kompanijos kaip Facebook, Google ar Amazon suprato, kad tradicinės SQL duomenų bazės nebeišsprendžia jų problemų su milžiniškais duomenų kiekiais ir paskirstytomis sistemomis.

Pagrindinis skirtumas nuo tradicinių reliacinių duomenų bazių – NoSQL sistemos neturi griežtos schemos, gali lengvai plėstis horizontaliai (pridedant daugiau serverių), ir jos optimizuotos specifiniams naudojimo atvejams. Tai nereiškia, kad jos geresnės už SQL – jos tiesiog kitokios, ir kiekvienai užduočiai reikia pasirinkti tinkamą įrankį.

Dokumentų duomenų bazės – lankstumas pirmoje vietoje

Dokumentų duomenų bazės yra turbūt populiariausias NoSQL tipas. MongoDB, CouchDB, Amazon DocumentDB – šie vardai jums tikriausiai kažką sako. Pagrindinis principas čia paprastas: duomenys saugomi kaip dokumentai, dažniausiai JSON arba BSON (Binary JSON) formatu.

Įsivaizduokite, kad kuriate el. parduotuvę. Tradicinėje SQL duomenų bazėje produkto informacija būtų išskaidyta po kelias lenteles – viena lentelė produktams, kita kategorijoms, trečia specifikacijoms. Su dokumentų duomenų baze viskas gali būti viename dokumente:

{
  "produktas_id": "12345",
  "pavadinimas": "Belaidės ausinės",
  "kaina": 89.99,
  "kategorijos": ["Elektronika", "Audio", "Ausinės"],
  "specifikacijos": {
    "bluetooth": "5.0",
    "baterija": "20 val",
    "spalvos": ["juoda", "balta", "mėlyna"]
  },
  "atsiliepimai": [
    {"autorius": "Jonas", "įvertinimas": 5, "komentaras": "Puikios!"}
  ]
}

Tokia struktūra leidžia greitai gauti visą informaciją vienu užklausimu, be sudėtingų JOIN operacijų. Tai ypač naudinga, kai jūsų duomenų struktūra nėra visiškai vienoda – vieni produktai gali turėti daugiau specifikacijų, kiti mažiau, ir tai visiškai normalu.

Praktiškai dokumentų duomenų bazes naudoju projektams, kur reikia greito prototipavimo, kur duomenų struktūra gali keistis, arba kur reikia saugoti sudėtingus, įdėtus objektus. Pavyzdžiui, turinio valdymo sistemoms (CMS), katalogams, vartotojų profiliams – tai idealus pasirinkimas.

Raktas-reikšmė duomenų bazės – greitis virš visko

Jei jums reikia maksimalaus greičio ir paprastumo, raktas-reikšmė (key-value) duomenų bazės – tai jūsų draugas. Redis, Memcached, Amazon DynamoDB – šios sistemos veikia pagal paprasčiausią principą: duodi raktą, gauni reikšmę. Kaip didžiulis hash map’as atmintyje.

Aš dažniausiai naudoju Redis keliems tikslams. Pirma, kaip cache’ą – kai turite brangią operaciją (pvz., sudėtingą SQL užklausą), rezultatą galite išsaugoti Redis’e su raktu ir grąžinti jį per milisekundes, kai tas pats dalykas prašomas vėl. Antra, sesijų valdymui – kai vartotojas prisijungia prie jūsų sistemos, sesijos duomenis galite laikyti Redis’e, ir visi jūsų serveriai gali juos pasiekti.

Štai paprastas pavyzdys, kaip tai galėtų atrodyti:

SET user:1000:session "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
EXPIRE user:1000:session 3600  // Sesija galioja 1 valandą

GET user:1000:session  // Grąžina sesijos duomenis

Redis taip pat puikiai tinka realaus laiko aplikacijoms – chat’ams, žaidimams, analitikai. Jis palaiko ne tik paprastas string reikšmes, bet ir sąrašus, rinkinius (sets), surūšiuotus rinkinius, hash’us. Galite daryti sudėtingesnes operacijas, pavyzdžiui, saugoti lyderių lentelę žaidime naudojant sorted set, ir tai veiks žaibiškai net su milijonais įrašų.

Bet raktas-reikšmė duomenų bazės turi apribojimų. Jos nėra skirtos sudėtingoms užklausoms – negalite paieškoti „visų vartotojų, kurių amžius tarp 25 ir 35 ir kurie gyvena Vilniuje”. Jums reikia žinoti tikslų raktą. Tai specialisto įrankis specifinėms užduotims.

Stulpelinės duomenų bazės – kai duomenų yra per daug

Stulpelinės (column-family) duomenų bazės, kaip Apache Cassandra ar HBase, atsirado sprendžiant labai specifinę problemą – kaip efektyviai saugoti ir apdoroti milžiniškus duomenų kiekius paskirstytose sistemose. Čia duomenys organizuojami ne eilutėmis (kaip tradicinėse duomenų bazėse), o stulpeliais.

Kodėl tai svarbu? Įsivaizduokite, kad turite milijardą eilučių su šimtu stulpelių, bet jums reikia analizuoti tik tris stulpelius. Tradicinėje duomenų bazėje reikėtų nuskaityti visas eilutes. Stulpelinėje – tik tuos tris stulpelius, kurie jums reikalingi. Tai dramatiškai sumažina I/O operacijas ir pagreitina analitines užklausas.

Cassandra yra ypač populiari, nes ji puikiai horizontaliai plečiasi ir neturi single point of failure. Netflix, Apple, Instagram – visos šios kompanijos naudoja Cassandra savo infrastruktūroje. Ji idealiai tinka:

  • Laiko eilučių duomenims (time-series data) – sensorių duomenys, logai, metrika
  • Didelio masto įrašymo operacijoms – kai per sekundę reikia įrašyti tūkstančius ar milijonus įrašų
  • Geografiškai paskirstytoms sistemoms – galite turėti duomenų centrus keliose šalyse

Tačiau Cassandra nėra paprasta. Jos duomenų modeliavimas reikalauja kitokio mąstymo – jums reikia modeliuoti duomenis pagal tai, kaip juos naudosite, o ne pagal jų loginę struktūrą. Tai vadinamasis „query-first” dizainas. Jei planuojate naudoti Cassandra, pasiruoškite investuoti laiko į mokymąsi.

Grafų duomenų bazės – ryšiai kaip pirmos klasės piliečiai

Grafų duomenų bazės, kaip Neo4j, Amazon Neptune ar ArangoDB, sprendžia problemą, su kuria tradicinės duomenų bazės kovoja – efektyvų ryšių valdymą. Jei jūsų duomenyse ryšiai tarp objektų yra tokie pat svarbūs kaip ir patys objektai, grafų duomenų bazė yra natūralus pasirinkimas.

Klasikinis pavyzdys – socialinis tinklas. Kaip greitai atsakyti į klausimą „Kas yra mano draugų draugai, kurie gyvena Kaune ir domisi fotografija?” SQL duomenų bazėje tai reikštų kelias JOIN operacijas, kurios tampa vis lėtesnės, kuo giliau einame į ryšių grandinę. Grafų duomenų bazėje tai natūrali operacija.

Neo4j naudoja Cypher užklausų kalbą, kuri yra intuityviai suprantama:

MATCH (jonas:Person {name: 'Jonas'})-[:FRIEND]->(friend)-[:FRIEND]->(fof)
WHERE fof.city = 'Kaunas' AND 'fotografija' IN fof.interests
RETURN fof.name

Ši užklausa randa draugų draugus su specifinėmis savybėmis, ir ji veikia efektyviai net su milijonais mazgų ir ryšių. Tai todėl, kad grafų duomenų bazėse ryšiai yra fiziškai saugomi ir indeksuojami, o ne apskaičiuojami užklausos metu.

Praktiškai grafų duomenų bazes naudoju ne tik socialiniams tinklams. Jos puikiai tinka:

  • Rekomendacijų sistemoms – „žmonės, kurie pirko tai, taip pat pirko…”
  • Sukčiavimo aptikimui – ieškant įtartinų ryšių tarp transakcijų
  • Žinių grafams ir semantinei paieškai
  • Tinklo ir IT infrastruktūros valdymui – serveriai, priklausomybės, ryšiai
  • Maršrutų planavimui ir logistikai

Vienas iš didžiausių grafų duomenų bazių privalumų – galimybė atlikti sudėtingą analizę, kuri būtų praktiškai neįmanoma su kitomis duomenų bazėmis. Pavyzdžiui, PageRank tipo algoritmai, bendruomenių aptikimas, trumpiausio kelio paieška – visa tai yra įtaisyta funkcionalumo dalis.

Hibridiniai sprendimai ir multi-model duomenų bazės

Realybė tokia, kad dažnai jums reikia ne vieno tipo duomenų bazės, o kelių. Ir čia pradeda komplikuotis architektūra – reikia palaikyti kelias sistemas, sinchronizuoti duomenis, mokėti skirtingas užklausų kalbas. Todėl atsirado multi-model duomenų bazės.

ArangoDB, OrientDB, Couchbase – šios sistemos gali veikti kaip dokumentų duomenų bazė, grafų duomenų bazė ir raktas-reikšmė saugykla vienu metu. Tai leidžia naudoti tinkamą modelį kiekvienai užduočiai, bet palaikyti tik vieną sistemą.

Pavyzdžiui, ArangoDB projekte galite saugoti produktų informaciją kaip dokumentus, vartotojų ryšius kaip grafą, o cache’ą kaip raktas-reikšmė poras. Viskas vienoje vietoje, su viena užklausų kalba (AQL), viena backup strategija, viena komanda, kurią reikia mokytis.

Tačiau yra ir trūkumų. Multi-model duomenų bazės dažnai nėra tokios optimizuotos specifinėms užduotims kaip specializuotos sistemos. MongoDB bus greitesnė dokumentų operacijoms nei ArangoDB dokumentų režimu. Neo4j bus efektyvesnė sudėtingoms grafų užklausoms. Tai klasikinis trade-off – universalumas prieš specializaciją.

Kaip pasirinkti tinkamą NoSQL duomenų bazę

Geriausias klausimas, kurį galite sau užduoti prieš pasirenkant duomenų bazę – ne „kuri yra geriausia?”, o „kuri yra tinkamiausia mano problemai?” Štai keletas praktinių klausimų, kurie padės apsispręsti:

Kokia jūsų duomenų struktūra? Jei turite hierarchinius, įdėtus duomenis, kurie natūraliai atitinka JSON struktūrą – dokumentų duomenų bazė. Jei jūsų duomenys yra labai susiję tarpusavyje ir ryšiai yra svarbūs – grafų duomenų bazė. Jei duomenys paprasti ir reikia tik greito prieigos – raktas-reikšmė.

Kokie jūsų skaitymo/rašymo patternai? Jei daug rašote, mažai skaitote – stulpelinė duomenų bazė. Jei daug skaitote, mažai rašote – dokumentų arba grafų. Jei reikia ekstremalaus skaitymo greičio – raktas-reikšmė su cache’avimu.

Kiek duomenų turėsite? Jei kalbame apie gigabaitus – beveik bet kuri NoSQL duomenų bazė tiks. Jei terabaitus ar petabaitus – žiūrėkite į Cassandra, HBase arba specializuotus sprendimus.

Ar reikia ACID garantijų? Daugelis NoSQL duomenų bazių aukoja griežtas ACID garantijas dėl našumo ir prieinamumo (CAP teorema). Jei jums būtina transakcijų atomika – MongoDB palaiko multi-document transakcijas, arba galbūt vis dėlto geriau naudoti PostgreSQL.

Kokia jūsų komandos patirtis? Tai praktiškas, bet svarbus klausimas. Jei jūsų komanda puikiai moka SQL, o projektas nėra kritiškai priklausomas nuo NoSQL privalumų – galbūt neverta komplikuoti. PostgreSQL su JSONB laukais gali būti geras kompromisas.

Aš asmeniškai dažniausiai renkuosi MongoDB naujiem projektam, nes ji turi gerą dokumentaciją, didelę bendruomenę, ir ji pakankamai universali daugeliui use case’ų. Bet tai nereiškia, kad ji visada tinkamiausia – kiekvieną kartą reikia vertinti individualiai.

Realūs scenarijai ir ko aš išmokau praktikoje

Per pastaruosius kelerius metus dirbau su įvairiais projektais, ir kiekvienas davė vertingų pamokų apie NoSQL duomenų bazes. Leiskite pasidalinti keliais realiais atvejais.

E-commerce platforma su MongoDB: Pradėjome su tradicine MySQL duomenų baze, bet greitai susidūrėme su problema – produktų atributai buvo labai skirtingi. Drabužiams reikėjo dydžių, spalvų, medžiagų. Elektronikai – techninių specifikacijų. Maistui – ingredientų, alergių informacijos. Bandėme spręsti su EAV (Entity-Attribute-Value) modeliu SQL’e, bet tai virto košmaru. Perėjimas į MongoDB leido kiekvienam produktui turėti savo unikalią struktūrą, ir viskas tapo daug paprasčiau.

Real-time analytics su Redis: Projektui reikėjo rodyti realaus laiko statistiką – kiek vartotojų dabar naršo svetainę, populiariausios kategorijos, aktyviausi regionai. Bandėme daryti tai su MySQL, bet serveris tiesiog nespėjo. Redis su sorted sets ir hyperloglog struktūromis išsprendė problemą – galėjome apdoroti tūkstančius event’ų per sekundę ir grąžinti statistiką per milisekundes.

Rekomendacijų sistema su Neo4j: Turėjome milijonus produktų ir vartotojų, ir reikėjo generuoti personalizuotas rekomendacijas. Pradžioje bandėme su SQL ir collaborative filtering algoritmais Python’e, bet tai buvo per lėta. Neo4j leido mums saugoti vartotojų-produktų-kategorijų grafą ir vykdyti sudėtingas graph traversal užklausas realiu laiku. Rekomendacijų kokybė pagerėjo, o atsakymo laikas sumažėjo nuo kelių sekundžių iki šimtų milisekundžių.

IoT duomenų saugojimas su Cassandra: Projektas rinkdavo duomenis iš tūkstančių sensorių kas kelias sekundes. Tai reiškė milijonus įrašų per dieną. MySQL tiesiog negalėjo susidoroti su tokiu rašymo krūviu. Cassandra buvo sukurta būtent tokiems atvejams – ji puikiai tvarko didelius write throughput, ir galėjome lengvai pridėti daugiau node’ų, kai duomenų kiekis augo.

Viena svarbi pamoka iš visų šių projektų – migracija nėra paprasta. Jei planuojate pereiti nuo SQL prie NoSQL (arba atvirkščiai), skirkite tam pakankamai laiko. Duomenų modeliavimas yra skirtingas, užklausų logika skiriasi, backup ir recovery procesai kitokie. Geriausia strategija – pradėti nuo nedidelės dalies sistemos, išmokti, kaip viskas veikia, ir tik tada plėstis toliau.

Ateitis ir kur link judame

NoSQL duomenų bazių pasaulis nuolat evoliucionuoja. Matau kelias aiškias tendencijas, kurios formuoja ateitį.

Pirma, ribos tarp SQL ir NoSQL nyksta. PostgreSQL dabar palaiko JSONB, full-text search, ir net kai kurias grafų operacijas. MongoDB įvedė multi-document transakcijas ir SQL-like užklausų kalbą. Sistemos tampa vis universalesnės, ir tai gerai – reiškia, kad galime naudoti tinkamą įrankį konkrečiai užduočiai, bet neprivalome mokėti dešimties skirtingų technologijų.

Antra, serverless ir managed servisai keičia žaidimo taisykles. AWS DynamoDB, Azure CosmosDB, MongoDB Atlas – šios paslaugos leidžia naudoti galingas NoSQL duomenų bazes be infrastruktūros valdymo. Jums nereikia konfigūruoti serverių, rūpintis backup’ais, scaling’u, security patches. Tiesiog naudojate API ir mokate už tai, ką sunaudojate. Tai ypač patrauklu startup’ams ir mažesnėms komandoms.

Trečia, AI ir machine learning integracijos tampa standartine funkcija. Vector search, kuris leidžia ieškoti panašių objektų pagal embedding’us, dabar yra daugelyje NoSQL duomenų bazių. Tai atveria naujas galimybes – semantinė paieška, rekomendacijos, anomalijų aptikimas – visa tai tampa lengviau įgyvendinama.

Ketvirta, edge computing kelia naujus iššūkius. Kai duomenys apdorojami ne tik centriniuose duomenų centruose, bet ir edge device’uose, reikia duomenų bazių, kurios gali veikti paskirstytai, su intermittent connectivity, ir sinchronizuotis, kai tik įmanoma. CouchDB ir PouchDB, Realm (dabar MongoDB Realm) – šios technologijos sprendžia būtent tokias problemas.

Praktiškai, jei šiandien pradėčiau naują projektą, tikriausiai rinktųčiau vieną iš managed NoSQL servisų, nebent turėčiau labai specifinių reikalavimų. Infrastruktūros valdymas atima per daug laiko, kurį geriau skirti produkto kūrimui. Ir naudočiau multi-model arba hibridinį požiūrį – pradėčiau su viena pagrindinę duomenų baze, bet būčiau pasirengęs pridėti specializuotą sprendimą, jei to reikėtų.

NoSQL duomenų bazės nėra sidabrinis kulka, kuris išsprendžia visas problemas. Jos yra įrankiai, ir kaip bet kurie įrankiai, turi savo stipriąsias ir silpnąsias puses. Svarbiausia – suprasti, kada ir kodėl jas naudoti. Jei jūsų projektas puikiai veikia su PostgreSQL, ir jūs nematote konkrečių problemų, kurių NoSQL išspręstų – neverta keisti tik dėl to, kad „taip dabar madinga”. Bet jei susidūrėte su scaling problemomis, sudėtinga duomenų struktūra, arba specifiniais naudojimo atvejais – NoSQL pasaulis turi sprendimą jums.

Daugiau

XML external entity (XXE) atakos