Osnove dizajna baze podataka - Poređenje PostgreSQL, Cassandra i MongoDB

Zdravo, prijatelji. Prije odlaska na drugi dio majskih praznika, s vama dijelimo materijal koji smo preveli u iščekivanju pokretanja novog streama po stopi "Relacioni DBMS".

Osnove dizajna baze podataka - Poređenje PostgreSQL, Cassandra i MongoDB

Programeri aplikacija provode dosta vremena uspoređujući više operativnih baza podataka kako bi odabrali onu koja najbolje funkcionira za njihovo predviđeno radno opterećenje. Potrebe mogu uključivati ​​pojednostavljeno modeliranje podataka, transakcijske garancije, performanse čitanja/pisanja, horizontalno skaliranje i toleranciju grešaka. Tradicionalno, izbor počinje sa kategorijom baze podataka, SQL ili NoSQL, pošto svaka kategorija pruža jasan skup kompromisa. Visoke performanse u smislu male latencije i velike propusnosti općenito se smatraju zahtjevom koji se ne može ugroziti i stoga je od suštinskog značaja za bilo koju bazu podataka u uzorku.

Svrha ovog članka je pomoći programerima aplikacija da naprave pravi izbor između SQL-a i NoSQL-a u kontekstu modeliranja podataka aplikacije. Pogledaćemo jednu SQL bazu podataka, odnosno PostgreSQL, i dve NoSQL baze podataka, Cassandra i MongoDB, kako bismo pokrili osnove dizajna baze podataka, kao što je kreiranje tabela, njihovo popunjavanje, čitanje podataka iz tabele i njihovo brisanje. U sljedećem članku ćemo svakako pogledati indekse, transakcije, JOIN-ove, TTL direktive i dizajn baze podataka zasnovan na JSON-u.

Koja je razlika između SQL-a i NoSQL-a?

SQL baze podataka povećavaju fleksibilnost aplikacije kroz ACID transakcijske garancije, kao i njihovu sposobnost da traže podatke koristeći JOIN-ove na neočekivane načine na vrhu postojećih normaliziranih modela relacijskih baza podataka.

S obzirom na njihovu monolitnu/jednočvornu arhitekturu i korištenje modela replikacije master-slave za redundantnost, tradicionalnim SQL bazama podataka nedostaju dvije važne karakteristike - linearnu skalabilnost pisanja (tj. automatsko razdvajanje na više čvorova) i automatski/nulti gubitak podataka. To znači da količina primljenih podataka ne može premašiti maksimalnu propusnost pisanja jednog čvora. Osim toga, neki privremeni gubitak podataka mora se uzeti u obzir radi tolerancije grešaka (u arhitekturi koja nije dijeljena). Ovdje morate imati na umu da se nedavna urezivanja još nisu odrazila u podređenoj kopiji. U SQL bazama podataka također je teško postići nikakva ažuriranja zastoja.

NoSQL baze podataka su obično distribuirane u prirodi, tj. u njima su podaci podijeljeni u sekcije i raspoređeni na nekoliko čvorova. Oni zahtijevaju denormalizaciju. To znači da se uneseni podaci također moraju više puta kopirati kako bi se odgovorilo na specifične zahtjeve koje šaljete. Opći cilj je postizanje visokih performansi smanjenjem broja dijelova dostupnih u vrijeme čitanja. Ovo implicira da NoSQL zahtijeva od vas da modelirate svoje upite, dok SQL zahtijeva od vas da modelirate svoje podatke.

NoSQL naglašava postizanje visokih performansi u distribuiranom klasteru i to je glavni razlog za mnoge kompromise u dizajnu baze podataka, koji uključuju gubitak ACID transakcija, JOIN-ova i konzistentnih globalnih sekundarnih indeksa.

Postoji mišljenje da iako NoSQL baze podataka pružaju linearnu skalabilnost pisanja i visoku toleranciju grešaka, gubitak transakcijskih garancija ih čini neprikladnim za kritične podatke.

Sljedeća tabela pokazuje kako se modeliranje podataka u NoSQL-u razlikuje od SQL-a.

Osnove dizajna baze podataka - Poređenje PostgreSQL, Cassandra i MongoDB

SQL i NoSQL: Zašto su potrebna oba?

Realne aplikacije s velikim brojem korisnika, kao što su Amazon.com, Netflix, Uber i Airbnb, odgovorne su za obavljanje složenih zadataka različitih vrsta. Na primjer, aplikacija za e-trgovinu kao što je Amazon.com mora pohraniti lagane, vrlo osjetljive podatke kao što su informacije o korisnicima, proizvodima, narudžbama, fakturama, zajedno s teškim, ali manje osjetljivim podacima kao što su recenzije proizvoda, poruke podrške., aktivnosti korisnika. , korisničke recenzije i preporuke. Naravno, ove aplikacije se oslanjaju na barem jednu SQL bazu podataka zajedno s barem jednom NoSQL bazom podataka. U međuregionalnim i globalnim sistemima, NoSQL baza podataka radi kao geo-distribuirana keš memorija za podatke pohranjene u pouzdanom izvoru, SQL bazi podataka, koja radi u bilo kojoj regiji.

Kako YugaByte DB kombinuje SQL i NoSQL?

Izgrađen na log orijentiranom mješovitom pogonu za pohranu, automatskom dijeljenju, podijeljenoj distribuiranoj replikaciji konsenzusa i ACID distribuiranim transakcijama (inspirirano Google Spannerom), YugaByte DB je prva svjetska baza podataka otvorenog koda koja je istovremeno kompatibilna s NoSQL (Cassandra & Redis). ) i SQL (PostgreSQL). Kao što je prikazano u tabeli ispod, YCQL, YugaByte DB API kompatibilan sa Cassandrom, dodaje koncepte ACID transakcija sa jednim i više ključeva i globalnih sekundarnih indeksa NoSQL API-ju, otvarajući tako eru transakcijskih NoSQL baza podataka. Pored toga, YCQL, YugaByte DB API kompatibilan sa PostgreSQL, dodaje koncepte linearnog skaliranja pisanja i automatskog prelaska na grešku u SQL API, donoseći distribuirane SQL baze podataka u svijet. Pošto je YugaByte DB baza podataka inherentno transakcijska, NoSQL API se sada može koristiti u kontekstu kritičnih podataka.

Osnove dizajna baze podataka - Poređenje PostgreSQL, Cassandra i MongoDB

Kao što je prethodno navedeno u članku "Predstavljamo YSQL: PostgreSQL kompatibilan distribuirani SQL API za YugaByte DB", izbor između SQL-a ili NoSQL-a u YugaByte DB-u u potpunosti ovisi o karakteristikama osnovnog radnog opterećenja:

  • Ako su vaše primarno radno opterećenje operacije JOIN s više ključeva, onda kada odaberete YSQL, imajte na umu da vaši ključevi mogu biti raspoređeni na više čvorova, što rezultira većom latencijom i/ili manjom propusnošću od NoSQL-a.
  • U suprotnom, odaberite bilo koji od dva NoSQL API-ja, imajući na umu da ćete dobiti bolje performanse kao rezultat upita koji se serviraju iz jednog po jednog čvora. YugaByte DB može poslužiti kao jedinstvena operativna baza podataka za stvarne složene aplikacije koje trebaju upravljati višestrukim radnim opterećenjem u isto vrijeme.

Laboratorija za modeliranje podataka u sljedećem odjeljku zasnovana je na PostgreSQL i Cassandra kompatibilnim YugaByte DB API-jima baze podataka, za razliku od originalnih baza podataka. Ovaj pristup naglašava lakoću interakcije sa dva različita API-ja (na dva različita porta) istog klastera baze podataka, za razliku od upotrebe potpuno nezavisnih klastera dve različite baze podataka.
U sljedećim odjeljcima ćemo pogledati Laboratoriju za modeliranje podataka kako bismo ilustrovali razliku i neke od zajedničkih karakteristika dotičnih baza podataka.

Laboratorija za modeliranje podataka

Instaliranje baza podataka

S obzirom na fokus na dizajnu modela podataka (umjesto složenih arhitektura implementacije), instalirat ćemo baze podataka u Docker kontejnere na lokalnom računalu, a zatim ćemo komunicirati s njima koristeći njihove odgovarajuće školjke komandne linije.

PostgreSQL i Cassandra kompatibilna, YugaByte DB baza podataka

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

Pristup komandnoj liniji

Povežimo se na baze podataka koristeći shell komandne linije za odgovarajuće API-je.

PostgreSQL

psql je ljuska komandne linije za interakciju sa PostgreSQL-om. Radi lakšeg korišćenja, YugaByte DB dolazi sa psql-om direktno u fascikli bin.

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

Cassandra

sqlsh je ljuska komandne linije za interakciju sa Cassandrom i njenim kompatibilnim bazama podataka putem CQL (Cassandra Query Language). Za jednostavnu upotrebu, YugaByte DB dolazi sa cqlsh u katalogu bin.
Imajte na umu da je CQL inspiriran SQL-om i ima slične koncepte tabela, redova, stupaca i indeksa. Međutim, kao NoSQL jezik, on dodaje određeni skup ograničenja, od kojih ćemo većinu pokriti u drugim člancima.

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

MongoDB

mongo je ljuska komandne linije za interakciju sa MongoDB. Može se naći u bin direktorijumu MongoDB instalacije.

docker exec -it my-mongo bash 
cd bin
mongo

Kreirajte tabelu

Sada možemo komunicirati s bazom podataka kako bismo izvršili različite operacije pomoću komandne linije. Počnimo sa kreiranjem tabele koja čuva informacije o pesmama koje su napisali različiti izvođači. Ove pjesme mogu biti dio albuma. Takođe opcioni atributi za pjesmu su godina izdanja, cijena, žanr i ocjena. Moramo uzeti u obzir dodatne atribute koji bi mogli biti potrebni u budućnosti kroz polje "tagovi". Može pohraniti polustrukturirane podatke kao parove ključ/vrijednost.

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

Kreiranje tabele u Cassandri je vrlo slično PostgreSQL-u. Jedna od glavnih razlika je odsustvo ograničenja integriteta (kao NOT NULL), ali to je odgovornost aplikacije, a ne NoSQL baze podataka.. Primarni ključ se sastoji od particionog ključa (kolona izvođača u primjeru ispod) i skupa kolona za grupisanje (kolona SongTitle u primjeru ispod). Ključ particije određuje u koju particiju/šard treba staviti red, a kolone za grupisanje pokazuju kako bi podaci trebali biti organizirani unutar trenutnog dijela.

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 organizira podatke u baze podataka (baza podataka) (slično Keyspace u Cassandri), gdje postoje kolekcije (kolekcije) (slično tabelama) koje sadrže dokumente (dokumente) (slično redovima u tabeli). U MongoDB, u principu, nije potrebna početna definicija šeme. Tim "koristi bazu podataka", prikazan ispod, instancira bazu podataka pri prvom pozivu i mijenja kontekst za novokreiranu bazu podataka. Čak ni kolekcije ne moraju biti eksplicitno kreirane, one se kreiraju automatski, baš kada se prvi dokument doda novoj kolekciji. Imajte na umu da MongoDB koristi probnu bazu podataka prema zadanim postavkama, tako da će se svaka operacija razine kolekcije bez specificiranja određene baze podataka izvoditi u njoj po defaultu.

use myNewDatabase;

Dobivanje informacija o stolu
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;

Unošenje podataka u tabelu
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

Generalno, izraz INSERT u Cassandri izgleda vrlo slično onom u PostgreSQL-u. Međutim, postoji jedna velika razlika u semantici. U Kasandri INSERT je zapravo operacija UPSERT, gdje se najnovije vrijednosti dodaju nizu, u slučaju da niz već postoji.

Unos podataka je sličan PostgreSQL-u INSERT viši

.

MongoDB

Iako je MongoDB NoSQL baza podataka poput Cassandre, njegova operacija unosa podataka nema nikakve veze sa Kasandrinim semantičkim ponašanjem. U MongoDB insert () nema priliku UPSERT, što ga čini sličnim PostgreSQL-u. Dodavanje zadanih podataka bez _idspecified će rezultirati dodavanjem novog dokumenta u kolekciju.

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"
}
}
);

Upit tabele

Možda najznačajnija razlika između SQL-a i NoSQL-a u smislu upita je upotreba FROM и WHERE. SQL dozvoljava izraz nakon FROM odaberite više tabela i izraz sa WHERE može biti bilo koje složenosti (uključujući operacije JOIN između stolova). Međutim, NoSQL ima tendenciju da nametne stroga ograničenja FROM, i rade sa samo jednom navedenom tablicom i u WHERE, primarni ključ uvijek mora biti specificiran. To je zbog želje za poboljšanjem performansi NoSQL-a, o čemu smo ranije govorili. Ova želja vodi ka svakom mogućem smanjenju bilo koje interakcije između kartica i ključeva. Može dovesti do velikog kašnjenja u komunikaciji među čvorovima kada se odgovara na zahtjev i stoga ga je u principu najbolje izbjegavati. Na primjer, Cassandra zahtijeva da zahtjevi budu ograničeni na određene operatere (dozvoljeno samo =, IN, <, >, =>, <=) na particijskim ključevima, osim kada se ispituje sekundarni indeks (ovdje je dozvoljen samo operator =).

PostgreSQL

Slijede tri primjera upita koje SQL baza podataka može lako izvršiti.

  • Prikaži sve pjesme izvođača;
  • Prikaži sve pjesme izvođača koje odgovaraju prvom dijelu naslova;
  • Prikaži sve pjesme izvođača koje imaju određenu riječ u naslovu i imaju cijenu manju od 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

Od gore navedenih PostgreSQL upita, samo će prvi raditi nepromijenjen u Cassandri, jer izjava LIKE ne može se primijeniti na grupiranje stupaca kao što je SongTitle. U ovom slučaju su dozvoljeni samo operateri = и 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

Kao što je prikazano u prethodnim primjerima, glavna metoda za kreiranje upita u MongoDB je db.collection.find(). Ova metoda eksplicitno sadrži naziv kolekcije (music u primjeru ispod), tako da nije dozvoljeno ispitivanje više kolekcija.

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

Čitanje svih redova tabele

Čitanje svih redova je samo poseban slučaj obrasca upita o kojem smo ranije govorili.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Slično kao u gornjem primjeru PostgreSQL.

MongoDB

db.music.find( {} );

Uređivanje podataka u tabeli

PostgreSQL

PostgreSQL daje izjavu UPDATE za promjenu podataka. Ona nema priliku UPSERT, tako da ova izjava neće uspjeti ako red više nije u bazi podataka.

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

Cassandra

Cassandra ima UPDATE slično PostgreSQL-u. UPDATE ima istu semantiku UPSERT, like INSERT.

Slično kao u gornjem primjeru PostgreSQL.

MongoDB
Operacija update () u MongoDB-u može u potpunosti ažurirati postojeći dokument ili ažurirati samo određena polja. Podrazumevano ažurira samo jedan dokument sa onemogućenom semantikom UPSERT. Osvježite više dokumenata i slično ponašanje UPSERT može se primijeniti postavljanjem dodatnih zastavica za operaciju. Kao na primjer u primjeru ispod, žanr određenog izvođača je ažuriran njegovom pjesmom.

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

Uklanjanje podataka iz tabele

PostgreSQL

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

Cassandra

Slično kao u gornjem primjeru PostgreSQL.

MongoDB

MongoDB ima dvije vrste operacija za brisanje dokumenata − deleteOne() /deleteMany() и ukloni (). Oba tipa brišu dokumente, ali vraćaju različite rezultate.

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

Brisanje tabele

PostgreSQL

DROP TABLE Music;

Cassandra

Slično kao u gornjem primjeru PostgreSQL.

MongoDB

db.music.drop();

zaključak

Debata oko izbora između SQL-a i NoSQL-a bjesni već više od 10 godina. Postoje dva glavna aspekta ove debate: arhitektura motora baze podataka (monolitni, transakcijski SQL naspram distribuiranog, netransakcionog NoSQL) i pristup dizajnu baze podataka (modeliranje podataka u SQL-u nasuprot modeliranju vaših upita u NoSQL-u).

Sa distribuiranom transakcionom bazom podataka kao što je YugaByte DB, debata o arhitekturi baze podataka može se lako raspršiti. Kako količine podataka postaju veće od onoga što se može upisati u jedan čvor, postaje neophodna potpuno distribuirana arhitektura koja podržava linearnu skalabilnost pisanja sa automatskim dijeljenjem/rebalansom.

Pored onoga što je rečeno u jednom od članaka Google CloudTransakcione, snažno konzistentne arhitekture su sada šire prihvaćene kako bi pružile bolju fleksibilnost razvoja od netransakcionih, konačno konzistentnih arhitektura.

Vraćajući se na raspravu o dizajnu baze podataka, pošteno je reći da su oba pristupa dizajnu (SQL i NoSQL) neophodna za svaku složenu aplikaciju u stvarnom svijetu. SQL-ov pristup "modeliranju podataka" omogućava programerima da lakše ispune promjenjive poslovne zahtjeve, dok NoSQL-ov pristup "modeliranju upita" omogućava tim istim programerima da rukuju velikim količinama podataka sa malim kašnjenjem i velikom propusnošću. Iz tog razloga YugaByte DB pruža SQL i NoSQL API-je u zajedničkoj jezgri i ne zagovara nijedan od pristupa. Pored toga, obezbeđujući kompatibilnost sa popularnim jezicima baza podataka, uključujući PostgreSQL i Cassandra, YugaByte DB osigurava da programeri ne moraju da uče drugi jezik da bi radili sa distribuiranim, snažno konzistentnim motorom baze podataka.

U ovom članku smo pogledali kako se osnove dizajna baze podataka razlikuju između PostgreSQL, Cassandre i MongoDB. U sljedećim člancima ćemo zaroniti u napredne koncepte dizajna kao što su indeksi, transakcije, JOIN-ovi, TTL direktive i JSON dokumenti.

Želimo vam ugodan vikend i pozivamo vas besplatni webinarkoji će se održati 14. maja.

izvor: www.habr.com

Dodajte komentar