Andmebaasi kujundamise põhialused – PostgreSQL, Cassandra ja MongoDB võrdlemine

Tere, sõbrad. Enne maipühade teisele osale lahkumist jagame teiega materjali, mille oleme tõlkinud, oodates uue voo käivitamist tempoga "Relatiivne DBMS".

Andmebaasi kujundamise põhialused – PostgreSQL, Cassandra ja MongoDB võrdlemine

Rakenduste arendajad kulutavad palju aega mitme töötava andmebaasi võrdlemisele, et valida välja see, mis nende kavandatud töökoormuse jaoks kõige paremini sobib. Vajadused võivad hõlmata lihtsustatud andmete modelleerimist, tehingutagatisi, lugemise/kirjutamise jõudlust, horisontaalset skaleerimist ja tõrketaluvust. Traditsiooniliselt algab valik andmebaasi kategooriast SQL või NoSQL, kuna iga kategooria pakub selgeid kompromisse. Kõrget jõudlust madala latentsusaja ja suure läbilaskevõime osas peetakse üldiselt nõudeks, mida ei saa kahjustada ja seetõttu on see oluline mis tahes valimisse kuuluva andmebaasi jaoks.

Selle artikli eesmärk on aidata rakenduste arendajatel teha rakenduste andmete modelleerimise kontekstis õige valik SQL-i ja NoSQL-i vahel. Vaatleme ühte SQL-i andmebaasi, nimelt PostgreSQL-i ja kahte NoSQL-i andmebaasi, Cassandra ja MongoDB, et hõlmata andmebaasi kujundamise põhitõdesid, nagu tabelite loomine, nende täitmine, andmete lugemine tabelist ja nende kustutamine. Järgmises artiklis vaatame kindlasti JSON-il põhinevaid indekseid, tehinguid, JOIN-e, TTL-i direktiive ja andmebaasi kujundust.

Mis vahe on SQL-il ja NoSQL-il?

SQL-andmebaasid suurendavad rakenduste paindlikkust ACID-i tehingugarantiide kaudu, samuti nende võimet teha JOIN-ide abil andmeid ootamatul viisil olemasolevate normaliseeritud relatsiooniandmebaasi mudelite kõrval.

Arvestades nende monoliitset/ühe sõlme arhitektuuri ja ülem-alluv replikatsioonimudeli kasutamist koondamiseks, puudub traditsioonilistel SQL-andmebaasidel kaks olulist funktsiooni – lineaarne kirjutamise skaleeritus (st automaatne jagamine mitme sõlme vahel) ja automaatne/null andmekadu. See tähendab, et vastuvõetud andmete hulk ei tohi ületada ühe sõlme maksimaalset kirjutamisvõimsust. Lisaks tuleb tõrketaluvuse tagamiseks (mittejagatud arhitektuuris) arvestada mõningase ajutise andmete kadumisega. Siin tuleb meeles pidada, et hiljutised sissekanded ei ole veel orjakoopias kajastatud. Samuti on SQL-andmebaasides raske saavutada ühtegi seisakuaja värskendust.

NoSQL-i andmebaasid on tüüpiliselt looduses hajutatud, s.t. neis on andmed jagatud osadeks ja jaotatud mitme sõlme vahel. Need nõuavad denormaliseerimist. See tähendab, et teie saadetud konkreetsetele päringutele vastamiseks tuleb sisestatud andmeid ka mitu korda kopeerida. Üldine eesmärk on saavutada kõrge jõudlus, vähendades lugemisajal saadaolevate kildude arvu. See tähendab, et NoSQL nõuab päringute modelleerimist, SQL aga andmete modelleerimist.

NoSQL rõhutab suure jõudluse saavutamist hajutatud klastris ja see on paljude andmebaasikujunduse kompromisside peamine põhjus, mis hõlmab ACID-tehingute, JOIN-ide ja järjepidevate globaalsete sekundaarsete indeksite kaotamist.

On arvamus, et kuigi NoSQL-andmebaasid pakuvad lineaarset kirjutamismastaapsust ja kõrget tõrketaluvust, muudab tehingugarantiide kaotamine need kriitiliste andmete jaoks sobimatuks.

Järgmine tabel näitab, kuidas andmete modelleerimine NoSQL-is erineb SQL-ist.

Andmebaasi kujundamise põhialused – PostgreSQL, Cassandra ja MongoDB võrdlemine

SQL ja NoSQL: miks on mõlemat vaja?

Paljude kasutajate arvuga reaalrakendused, nagu Amazon.com, Netflix, Uber ja Airbnb, vastutavad mitmesuguste keerukate ülesannete täitmise eest. Näiteks peab e-kaubanduse rakendus, nagu Amazon.com, salvestama kergeid ja tundlikke andmeid, nagu teave kasutajate, toodete, tellimuste, arvete kohta, koos raskete, kuid vähem tundlike andmetega, nagu tooteülevaated, tugisõnumid. , kasutajate ülevaated ja soovitused. Loomulikult tuginevad need rakendused vähemalt ühele SQL-i andmebaasile ja vähemalt ühele NoSQL-i andmebaasile. Piirkondadevahelistes ja globaalsetes süsteemides töötab NoSQL-i andmebaas geograafiliselt hajutatud vahemäluna usaldusväärsesse allikasse, SQL-i andmebaasi, salvestatud andmete jaoks, mis toimivad ühes piirkonnas.

Kuidas ühendab YugaByte DB SQL-i ja NoSQL-i?

YugaByte DB, mis on üles ehitatud logipõhisele segasalvestusmootorile, automaatsele jagamisele, killustatud hajutatud konsensusreplikatsioonile ja ACID hajutatud tehingutele (inspireeritud Google Spannerist), on maailma esimene avatud lähtekoodiga andmebaas, mis ühildub samaaegselt ka NoSQL-iga (Cassandra ja Redis). ) ja SQL (PostgreSQL). Nagu on näidatud allolevas tabelis, lisab Cassandraga ühilduv YugaByte DB API YCQL NoSQL API-le ühe- ja mitme võtmega ACID-tehingute ja globaalsete sekundaarsete indeksite mõisted, juhatades sellega sisse tehingute NoSQL-i andmebaaside ajastu. Lisaks lisab PostgreSQL-iga ühilduv YugaByte DB API YCQL SQL API-le lineaarse kirjutamise skaleerimise ja automaatse tõrkesiirde kontseptsioonid, tuues hajutatud SQL-andmebaasid maailma. Kuna YugaByte DB andmebaas on oma olemuselt tehingupõhine, saab NoSQL API-d nüüd kasutada kriitiliste andmete kontekstis.

Andmebaasi kujundamise põhialused – PostgreSQL, Cassandra ja MongoDB võrdlemine

Nagu artiklis varem öeldud "Tutvustame YSQL-i: PostgreSQL-iga ühilduv hajutatud SQL API Yugabyte DB jaoks", sõltub YugaByte DB-s SQL-i või NoSQL-i valik täielikult aluseks oleva töökoormuse omadustest:

  • Kui teie peamine töökoormus on mitme võtmega JOIN-i toimingud, siis YSQL-i valimisel pidage meeles, et teie võtmed võivad olla hajutatud mitme sõlme vahel, mille tulemuseks on suurem latentsusaeg ja/või väiksem läbilaskevõime kui NoSQL-il.
  • Vastasel juhul valige üks kahest NoSQL API-st, pidades meeles, et ühest sõlmest korraga esitatavate päringute tulemusel saate parema jõudluse. YugaByte DB võib toimida ühe toimiva andmebaasina tõeliste keerukate rakenduste jaoks, mis peavad korraga haldama mitut töökoormust.

Järgmise jaotise andmete modelleerimise labor põhineb PostgreSQL-i ja Cassandraga ühilduvatel YugaByte DB andmebaasi API-del, erinevalt algsetest andmebaasidest. See lähenemisviis rõhutab sama andmebaasiklastri kahe erineva API-ga (kahe erineva pordiga) suhtlemise lihtsust, mitte aga kahe erineva andmebaasi täiesti sõltumatute klastrite kasutamist.
Järgmistes osades heidame pilgu andmemodelleerimislaborile, et illustreerida kõnealuste andmebaaside erinevusi ja mõningaid ühiseid jooni.

Andmete modelleerimise labor

Andmebaaside installimine

Arvestades keskendumist andmemudelite disainile (mitte keerukatele juurutusarhitektuuridele), installime andmebaasid Dockeri konteineritesse kohalikku masinasse ja seejärel suhtleme nendega, kasutades nende vastavaid käsurea kestasid.

PostgreSQL ja Cassandra ühilduv, YugaByte DB andmebaas

mkdir ~/yugabyte && cd ~/yugabyte
wget https://downloads.yugabyte.com/yb-docker-ctl && chmod +x yb-docker-ctl
docker pull yugabytedb/yugabyte
./yb-docker-ctl create --enable_postgres

MongoDB

docker run --name my-mongo -d mongo:latest

Käsurea juurdepääs

Loome andmebaasidega ühenduse vastavate API-de käsurea kesta abil.

PostgreSQL

psql on käsurea kest PostgreSQL-iga suhtlemiseks. Kasutamise hõlbustamiseks on YugaByte DB-ga kaasas psql otse prügikasti kaustas.

docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres

Cassandra

sqlsh on käsurea kest Cassandra ja selle ühilduvate andmebaasidega suhtlemiseks CQL-i (Cassandra Query Language) kaudu. Kasutamise hõlbustamiseks on YugaByte DB kaasas cqlsh kataloogis bin.
Pange tähele, et CQL on inspireeritud SQL-ist ja sellel on sarnased tabelite, ridade, veergude ja indeksite kontseptsioonid. NoSQL-keelena lisab see aga teatud piiranguid, millest enamikku käsitleme ka teistes artiklites.

docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh

MongoDB

Mongo on käsurea kest MongoDB-ga suhtlemiseks. Selle leiate MongoDB installi bin kataloogist.

docker exec -it my-mongo bash 
cd bin
mongo

Looge tabel

Nüüd saame andmebaasiga suhelda, et käsurea abil erinevaid toiminguid teha. Alustame tabeli loomisega, mis salvestab teavet erinevate artistide kirjutatud lugude kohta. Need laulud võivad olla osa albumist. Loo valikulised atribuudid on ka väljalaskeaasta, hind, žanr ja reiting. Peame arvestama täiendavate atribuutidega, mida võib tulevikus vaja minna välja "sildid" kaudu. See võib salvestada poolstruktureeritud andmeid võtme-väärtuste paaridena.

PostgreSQL

CREATE TABLE Music (
    Artist VARCHAR(20) NOT NULL, 
    SongTitle VARCHAR(30) NOT NULL,
    AlbumTitle VARCHAR(25),
    Year INT,
    Price FLOAT,
    Genre VARCHAR(10),
    CriticRating FLOAT,
    Tags TEXT,
    PRIMARY KEY(Artist, SongTitle)
);	

Cassandra

Tabeli loomine Cassandras on väga sarnane PostgreSQL-iga. Üks peamisi erinevusi on terviklikkuse piirangute puudumine (nagu NOT NULL), kuid see on rakenduse, mitte NoSQL-i andmebaasi vastutus.. Primaarvõti koosneb partitsioonivõtmest (allolevas näites esitaja veerg) ja klastrite veergude komplektist (allolevas näites veerg SongTitle). Sektsioonivõti määrab, millisesse partitsiooni/killu rida paigutada, ja rühmitusveerud näitavad, kuidas praeguses killus olevad andmed tuleks korraldada.

CREATE KEYSPACE myapp;
USE myapp;
CREATE TABLE Music (
    Artist TEXT, 
    SongTitle TEXT,
    AlbumTitle TEXT,
    Year INT,
    Price FLOAT,
    Genre TEXT,
    CriticRating FLOAT,
    Tags TEXT,
    PRIMARY KEY(Artist, SongTitle)
);

MongoDB

MongoDB korraldab andmed andmebaasidesse (Database) (sarnaselt Cassandra Keyspace'iga), kus on kogusid (kogud) (sarnaselt tabelitega), mis sisaldavad dokumente (Documents) (sarnaselt tabeli ridadele). MongoDB-s pole põhimõtteliselt esialgset skeemi määratlust vaja. Meeskond "kasuta andmebaasi"Allpool näidatud , loob andmebaasi esimesel kõnel ja muudab vastloodud andmebaasi konteksti. Isegi kogusid pole vaja otseselt luua, need luuakse automaatselt, just siis, kui uude kogusse lisatakse esimene dokument. Pange tähele, et MongoDB kasutab vaikimisi testandmebaasi, nii et kõik kogutaseme toimingud ilma konkreetset andmebaasi määramata tehakse selles vaikimisi.

use myNewDatabase;

Teabe hankimine tabeli kohta
PostgreSQL

d Music
Table "public.music"
    Column    |         Type          | Collation | Nullable | Default 
--------------+-----------------------+-----------+----------+--------
 artist       | character varying(20) |           | not null | 
 songtitle    | character varying(30) |           | not null | 
 albumtitle   | character varying(25) |           |          | 
 year         | integer               |           |          | 
 price        | double precision      |           |          | 
 genre        | character varying(10) |           |          | 
 criticrating | double precision      |           |          | 
 tags         | text                  |           |          | 
Indexes:
    "music_pkey" PRIMARY KEY, btree (artist, songtitle)

Cassandra

DESCRIBE TABLE MUSIC;
CREATE TABLE myapp.music (
    artist text,
    songtitle text,
    albumtitle text,
    year int,
    price float,
    genre text,
    tags text,
    PRIMARY KEY (artist, songtitle)
) WITH CLUSTERING ORDER BY (songtitle ASC)
    AND default_time_to_live = 0
    AND transactions = {'enabled': 'false'};

MongoDB

use myNewDatabase;
show collections;

Andmete sisestamine tabelisse
PostgreSQL

INSERT INTO Music 
    (Artist, SongTitle, AlbumTitle, 
    Year, Price, Genre, CriticRating, 
    Tags)
VALUES(
    'No One You Know', 'Call Me Today', 'Somewhat Famous',
    2015, 2.14, 'Country', 7.8,
    '{"Composers": ["Smith", "Jones", "Davis"],"LengthInSeconds": 214}'
);
INSERT INTO Music 
    (Artist, SongTitle, AlbumTitle, 
    Price, Genre, CriticRating)
VALUES(
    'No One You Know', 'My Dog Spot', 'Hey Now',
    1.98, 'Country', 8.4
);
INSERT INTO Music 
    (Artist, SongTitle, AlbumTitle, 
    Price, Genre)
VALUES(
    'The Acme Band', 'Look Out, World', 'The Buck Starts Here',
    0.99, 'Rock'
);
INSERT INTO Music 
    (Artist, SongTitle, AlbumTitle, 
    Price, Genre, 
    Tags)
VALUES(
    'The Acme Band', 'Still In Love', 'The Buck Starts Here',
    2.47, 'Rock', 
    '{"radioStationsPlaying": ["KHCR", "KBQX", "WTNR", "WJJH"], "tourDates": { "Seattle": "20150625", "Cleveland": "20150630"}, "rotation": Heavy}'
);

Cassandra

Üldiselt väljend INSERT Cassandras näeb välja väga sarnane PostgreSQL-iga. Semantikas on aga üks suur erinevus. Cassandras INSERT on tegelikult operatsioon UPSERT, kus stringile lisatakse uusimad väärtused, juhul kui string on juba olemas.

Andmesisestus sarnaneb PostgreSQL-iga INSERT üle

.

MongoDB

Kuigi MongoDB on NoSQL-i andmebaas nagu Cassandra, pole selle andmesisestustoimingul Cassandra semantilise käitumisega midagi pistmist. MongoDB-s sisesta () pole võimalust UPSERT, mis teeb selle sarnaseks PostgreSQL-iga. Vaikeandmete lisamine ilma _idspecified tulemusel lisatakse kogusse uus dokument.

db.music.insert( {
artist: "No One You Know",
songTitle: "Call Me Today",
albumTitle: "Somewhat Famous",
year: 2015,
price: 2.14,
genre: "Country",
tags: {
Composers: ["Smith", "Jones", "Davis"],
LengthInSeconds: 214
}
}
);
db.music.insert( {
artist: "No One You Know",
songTitle: "My Dog Spot",
albumTitle: "Hey Now",
price: 1.98,
genre: "Country",
criticRating: 8.4
}
);
db.music.insert( {
artist: "The Acme Band",
songTitle: "Look Out, World",
albumTitle:"The Buck Starts Here",
price: 0.99,
genre: "Rock"
}
);
db.music.insert( {
artist: "The Acme Band",
songTitle: "Still In Love",
albumTitle:"The Buck Starts Here",
price: 2.47,
genre: "Rock",
tags: {
radioStationsPlaying:["KHCR", "KBQX", "WTNR", "WJJH"],
tourDates: {
Seattle: "20150625",
Cleveland: "20150630"
},
rotation: "Heavy"
}
}
);

Tabeli päring

Võib-olla on kõige olulisem erinevus SQL-i ja NoSQL-i vahel päringute tegemisel selle kasutamine FROM и WHERE. SQL lubab pärast väljendit FROM valige mitu tabelit ja avaldis koos WHERE võib olla mis tahes keerukusega (kaasa arvatud toimingud JOIN laudade vahel). Kuid NoSQL kipub kehtestama range piirangu FROMja töötage ainult ühe määratud tabeliga ja sisse WHERE, tuleb alati määrata esmane võti. Selle põhjuseks on soov parandada NoSQL-i jõudlust, millest me varem rääkisime. See soov viib kõigi vahelehtede ja võtmetevahelise interaktsiooni vähendamiseni. See võib päringule vastamisel tekitada sõlmedevahelises suhtluses suure viivituse ja seetõttu on seda põhimõtteliselt kõige parem vältida. Näiteks nõuab Cassandra päringute piiramist teatud operaatoritega (lubatud ainult =, IN, <, >, =>, <=) partitsioonivõtmetel, välja arvatud teisese indeksi päringu tegemisel (siin on lubatud ainult operaator =).

PostgreSQL

Järgnevalt on toodud kolm näidet päringutest, mida SQL-andmebaas saab hõlpsasti täita.

  • Kuvage kõik artisti laulud;
  • Kuva kõik esitaja lood, mis vastavad pealkirja esimesele osale;
  • Kuvage kõik esitaja lood, mille pealkirjas on teatud sõna ja mille hind on alla 1.00.
SELECT * FROM Music
WHERE Artist='No One You Know';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE '%Today%'
AND Price > 1.00;

Cassandra

Ülalloetletud PostgreSQL-i päringutest töötab Cassandras muutmata kujul ainult esimene, kuna avaldus LIKE ei saa rakendada klastrite veergudele, näiteks SongTitle. Sel juhul on lubatud ainult operaatorid = и IN.

SELECT * FROM Music
WHERE Artist='No One You Know';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle IN ('Call Me Today', 'My Dog Spot')
AND Price > 1.00;

MongoDB

Nagu eelmistes näidetes näidatud, on MongoDB-s päringute loomise peamine meetod db.collection.find(). See meetod sisaldab selgesõnaliselt kogu nime (music allolevas näites), seega pole päringute tegemine mitmest kogust lubatud.

db.music.find( {
  artist: "No One You Know"
 } 
);
db.music.find( {
  artist: "No One You Know",
  songTitle: /Call/
 } 
);

Tabeli kõigi ridade lugemine

Kõikide ridade lugemine on vaid päringumustri erijuhtum, millest me varem rääkisime.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Sarnaselt ülaltoodud PostgreSQL-i näitele.

MongoDB

db.music.find( {} );

Andmete redigeerimine tabelis

PostgreSQL

PostgreSQL pakub avalduse UPDATE andmete muutmiseks. Tal pole võimalust UPSERT, nii et see avaldus nurjub, kui rida pole enam andmebaasis.

UPDATE Music
SET Genre = 'Disco'
WHERE Artist = 'The Acme Band' AND SongTitle = 'Still In Love';

Cassandra

Cassandra on UPDATE sarnane PostgreSQL-iga. UPDATE on sama semantika UPSERT, nagu INSERT.

Sarnaselt ülaltoodud PostgreSQL-i näitele.

MongoDB
Operatsioon värskendus () MongoDB-s saab see täielikult värskendada olemasolevat dokumenti või värskendada ainult teatud välju. Vaikimisi värskendab see ainult ühte dokumenti, mille semantika on keelatud UPSERT. Värskendage mitut dokumenti ja sarnast käitumist UPSERT saab rakendada, määrates toimingule täiendavad lipud. Nagu näiteks allolevas näites, värskendatakse konkreetse artisti žanrit tema laulu järgi.

db.music.update(
  {"artist": "The Acme Band"},
  { 
    $set: {
      "genre": "Disco"
    }
  },
  {"multi": true, "upsert": true}
);

Andmete eemaldamine tabelist

PostgreSQL

DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';

Cassandra

Sarnaselt ülaltoodud PostgreSQL-i näitele.

MongoDB

MongoDB-l on dokumentide kustutamiseks kahte tüüpi toiminguid – deleteOne() /deleteMany() и eemalda (). Mõlemad tüübid kustutavad dokumente, kuid annavad erinevaid tulemusi.

db.music.deleteMany( {
        artist: "The Acme Band"
    }
);

Tabeli kustutamine

PostgreSQL

DROP TABLE Music;

Cassandra

Sarnaselt ülaltoodud PostgreSQL-i näitele.

MongoDB

db.music.drop();

Järeldus

Arutelu SQL-i ja NoSQL-i vahelise valiku üle on kestnud üle 10 aasta. Sellel arutelul on kaks peamist aspekti: andmebaasimootori arhitektuur (monoliitne, tehingupõhine SQL vs. hajutatud, tehinguteta NoSQL) ja lähenemine andmebaasi kujundamisele (andmete modelleerimine SQL-is vs. päringute modelleerimine NoSQL-is).

Jaotatud tehinguandmebaasiga, nagu YugaByte DB, saab andmebaasi arhitektuuri arutelu hõlpsalt hajutada. Kuna andmemahud muutuvad suuremaks, kui ühte sõlme saab kirjutada, muutub vajalikuks täielikult hajutatud arhitektuur, mis toetab lineaarset kirjutamise mastaapsust koos automaatse killustamise/tasakaalustamisega.

Lisaks ühes artiklis öeldule Google Cloud, tehingupõhiseid, tugevalt järjekindlaid arhitektuure on nüüd laialdasemalt kasutusele võetud, et pakkuda paremat arenduspaindlikkust kui mittetehingulised, lõpuks järjekindlad arhitektuurid.

Andmebaasi kujundamise arutelu juurde tagasi tulles on õiglane öelda, et iga keeruka reaalmaailma rakenduse jaoks on vajalikud mõlemad disainilahendused (SQL ja NoSQL). SQL-i "andmete modelleerimise" lähenemisviis võimaldab arendajatel hõlpsamini vastata muutuvatele ärinõuetele, samas kui NoSQL-i "päringu modelleerimise" lähenemisviis võimaldab neil samadel arendajatel käsitleda suuri andmemahtusid madala latentsusaja ja suure läbilaskevõimega. Just sel põhjusel pakub YugaByte DB SQL-i ja NoSQL-i API-sid ühises tuumas ega poolda ühtegi lähenemisviisi. Lisaks, pakkudes ühilduvust populaarsete andmebaasi keeltega, sealhulgas PostgreSQL ja Cassandra, tagab YugaByte DB, et arendajad ei pea õppima teist keelt, et töötada hajutatud tugevalt järjepideva andmebaasimootoriga.

Selles artiklis vaatlesime, kuidas PostgreSQL-i, Cassandra ja MongoDB andmebaasi kujundamise põhialused erinevad. Järgmistes artiklites käsitleme täiustatud kujunduskontseptsioone, nagu indeksid, tehingud, JOIN-id, TTL-direktiivid ja JSON-dokumendid.

Soovime teile toredat nädalavahetust ja kutsume teid tasuta veebiseminarmis toimub 14. mail.

Allikas: www.habr.com

Lisa kommentaar