Základy návrhu databázy – Porovnanie PostgreSQL, Cassandra a MongoDB

Dobrý deň, priatelia. Pred odchodom na druhú časť májových prázdnin sa s vami delíme o materiál, ktorý sme preložili v očakávaní spustenia nového streamu na kurze "Relačný DBMS".

Základy návrhu databázy – Porovnanie PostgreSQL, Cassandra a MongoDB

Vývojári aplikácií trávia veľa času porovnávaním viacerých operačných databáz, aby vybrali tú, ktorá najlepšie vyhovuje zamýšľanému pracovnému zaťaženiu. Potreby môžu zahŕňať zjednodušené dátové modelovanie, transakčné záruky, výkon čítania/zápisu, horizontálne škálovanie a odolnosť voči chybám. Tradične sa výber začína kategóriou databázy, SQL alebo NoSQL, pretože každá kategória predstavuje jasný súbor kompromisov. Vysoký výkon z hľadiska nízkej latencie a vysokej priepustnosti sa vo všeobecnosti považuje za neobchodnú požiadavku, a preto je nevyhnutný pre akúkoľvek vzorovú databázu.

Účelom tohto článku je pomôcť vývojárom aplikácií urobiť správnu voľbu medzi SQL a NoSQL v kontexte aplikačného dátového modelovania. Pozrieme sa na jednu SQL databázu, konkrétne PostgreSQL, a dve NoSQL databázy, Cassandra a MongoDB, aby sme pokryli základy návrhu databázy, ako je vytváranie tabuliek, ich napĺňanie, čítanie údajov z tabuľky a ich mazanie. V ďalšom článku sa určite pozrieme na indexy, transakcie, JOINy, TTL direktívy a návrh databáz založený na JSON.

Aký je rozdiel medzi SQL a NoSQL?

SQL databázy zvyšujú flexibilitu aplikácií prostredníctvom ACID transakčných záruk, ako aj ich schopnosť dotazovať sa na dáta pomocou JOINs neočakávaným spôsobom nad rámec existujúcich normalizovaných modelov relačných databáz.

Vzhľadom na ich monolitickú/jednouzlovú architektúru a použitie modelu replikácie master-slave pre redundanciu, tradičným SQL databázam chýbajú dve dôležité funkcie – lineárna škálovateľnosť zápisu (t. j. automatické rozdelenie na viacero uzlov) a automatická/nulová strata dát. To znamená, že množstvo prijatých dát nemôže prekročiť maximálnu priepustnosť zápisu jedného uzla. Okrem toho je potrebné vziať do úvahy určitú dočasnú stratu údajov v rámci odolnosti voči chybám (v architektúre zdieľaného ničoho). Tu musíte mať na pamäti, že nedávne odovzdania sa ešte neodrazili v podriadenej kópii. V databázach SQL je tiež ťažké dosiahnuť aktualizácie bez výpadkov.

NoSQL databázy sú zvyčajne distribuované podľa povahy, t.j. v nich sú dáta rozdelené do sekcií a distribuované cez niekoľko uzlov. Vyžadujú denormalizáciu. To znamená, že zadané údaje musia byť tiež niekoľkokrát skopírované, aby bolo možné reagovať na konkrétne požiadavky, ktoré odošlete. Celkovým cieľom je dosiahnuť vysoký výkon znížením počtu zlomkov dostupných počas čítania. To znamená, že NoSQL vyžaduje, aby ste modelovali svoje dotazy, zatiaľ čo SQL vyžaduje, aby ste modelovali svoje údaje.

NoSQL sa zameriava na dosiahnutie vysokého výkonu v distribuovanom klastri a to je základný dôvod pre mnohé kompromisy pri návrhu databázy, ktoré zahŕňajú stratu transakcií ACID, JOINy ​​a konzistentné globálne sekundárne indexy.

Existuje argument, že zatiaľ čo databázy NoSQL poskytujú lineárnu škálovateľnosť zápisu a vysokú odolnosť voči chybám, strata transakčných záruk ich robí nevhodnými pre kritické údaje.

Nasledujúca tabuľka ukazuje, ako sa modelovanie údajov v NoSQL líši od SQL.

Základy návrhu databázy – Porovnanie PostgreSQL, Cassandra a MongoDB

SQL a NoSQL: Prečo sú potrebné obe?

Aplikácie v reálnom svete s veľkým počtom používateľov, ako sú Amazon.com, Netflix, Uber a Airbnb, majú za úlohu vykonávať zložité, mnohostranné úlohy. Napríklad aplikácia elektronického obchodu, ako je Amazon.com, potrebuje ukladať ľahké, veľmi dôležité údaje, ako sú informácie o používateľovi, produkty, objednávky, faktúry, spolu s ťažkými a menej citlivými údajmi, ako sú recenzie produktov, správy podpory, aktivita používateľov, užívateľské recenzie a odporúčania. Prirodzene, tieto aplikácie sa spoliehajú aspoň na jednu SQL databázu spolu s aspoň jednou NoSQL databázou. V medziregionálnych a globálnych systémoch databáza NoSQL funguje ako geograficky distribuovaná vyrovnávacia pamäť pre údaje uložené v dôveryhodnej zdrojovej databáze SQL spustenej v určitom regióne.

Ako YugaByte DB kombinuje SQL a NoSQL?

YugaByte DB, postavená na logisticky orientovanom motore zmiešaného úložiska, automatickom shardingu, sharded distribuovanej replikácii konsenzu a ACID distribuovaných transakciách (inšpirované Google Spannerom), je YugaByte DB prvou open source databázou na svete, ktorá je súčasne kompatibilná s NoSQL (Cassandra & Redis ) a SQL (PostgreSQL). Ako je uvedené v tabuľke nižšie, YCQL, YugaByte DB API kompatibilné s Cassandrou, pridáva do NoSQL API koncepty jedno- a viackľúčových ACID transakcií a globálnych sekundárnych indexov, čím otvára éru transakčných NoSQL databáz. Okrem toho YCQL, YugaByte DB API kompatibilné s PostgreSQL, pridáva do SQL API koncepty lineárneho škálovania zápisu a automatickej odolnosti voči chybám, čím prináša svetu distribuované SQL databázy. Pretože YugaByte DB má transakčný charakter, rozhranie NoSQL API je teraz možné použiť v kontexte kritických údajov.

Základy návrhu databázy – Porovnanie PostgreSQL, Cassandra a MongoDB

Ako už bolo uvedené v článku „Predstavujeme YSQL: PostgreSQL kompatibilné distribuované SQL API pre YugaByte DB“, výber medzi SQL alebo NoSQL v YugaByte DB úplne závisí od charakteristík základného pracovného zaťaženia:

  • Ak sú vašou primárnou záťažou operácie JOIN s viacerými kľúčmi, potom pri výbere YSQL berte na vedomie, že vaše kľúče môžu byť distribuované medzi viacero uzlov, čo má za následok vyššiu latenciu a/alebo nižšiu priepustnosť ako NoSQL.
  • V opačnom prípade si vyberte jedno z dvoch rozhraní API NoSQL, pričom majte na pamäti, že získate lepší výkon v dôsledku dopytov obsluhovaných z jedného uzla naraz. YugaByte DB môže slúžiť ako jedna operačná databáza pre komplexné aplikácie v reálnom svete, ktoré potrebujú spravovať viacero pracovných zaťažení súčasne.

Laboratórium modelovania údajov v ďalšej časti je založené na databázach YugaByte DB kompatibilných s PostgreSQL a Cassandra API, na rozdiel od natívnych databáz. Tento prístup zdôrazňuje jednoduchosť interakcie s dvoma rôznymi API (na dvoch rôznych portoch) toho istého databázového klastra, na rozdiel od používania úplne nezávislých klastrov dvoch rôznych databáz.
V nasledujúcich častiach sa pozrieme na laboratórium modelovania údajov, aby sme ilustrovali rozdiely a niektoré spoločné znaky pokrytých databáz.

Laboratórium modelovania údajov

Inštalácia databázy

Vzhľadom na dôraz na návrh dátového modelu (namiesto zložitých architektúr nasadenia) nainštalujeme databázy do kontajnerov Docker na lokálnom počítači a potom s nimi interagujeme pomocou ich príslušných shellov príkazového riadku.

Databáza YugaByte DB kompatibilná s PostgreSQL a Cassandra

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

Prístup k príkazovému riadku

Pripojme sa k databázam pomocou príkazového riadka pre príslušné API.

PostgreSQL

psql je shell príkazového riadka na interakciu s PostgreSQL. Pre jednoduché použitie sa YugaByte DB dodáva s psql priamo v priečinku bin.

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

Cassandra

cqlsh je shell príkazového riadka na interakciu s Cassandrou a jej kompatibilnými databázami prostredníctvom CQL (Cassandra Query Language). Pre jednoduché použitie je dodávaný YugaByte DB cqlsh v katalógu bin.
Všimnite si, že CQL bol inšpirovaný SQL a má podobné koncepty tabuliek, riadkov, stĺpcov a indexov. Ako jazyk NoSQL však pridáva určitý súbor obmedzení, z ktorých väčšine sa budeme venovať aj v iných článkoch.

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

MongoDB

Mongo je shell príkazového riadka na interakciu s MongoDB. Nájdete ho v adresári bin inštalácie MongoDB.

docker exec -it my-mongo bash 
cd bin
mongo

Vytvorte tabuľku

Teraz môžeme interagovať s databázou a vykonávať rôzne operácie pomocou príkazového riadku. Začnime vytvorením tabuľky, v ktorej sú uložené informácie o skladbách napísaných rôznymi interpretmi. Tieto skladby môžu byť súčasťou albumu. Tiež voliteľné atribúty pre skladbu sú rok vydania, cena, žáner a hodnotenie. Prostredníctvom poľa „značky“ musíme zohľadniť ďalšie atribúty, ktoré môžu byť v budúcnosti potrebné. Dokáže ukladať pološtruktúrované dáta vo forme párov kľúč – hodnota.

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

Vytvorenie tabuľky v Cassandra je veľmi podobné PostgreSQL. Jedným z hlavných rozdielov je nedostatok obmedzení integrity (napr. NOT NULL), ale to je zodpovednosťou aplikácie, nie databázy NoSQL.. Primárny kľúč pozostáva z kľúča rozdelenia (stĺpec Artist v príklade nižšie) a sady klastrových stĺpcov (stĺpec SongTitle v príklade nižšie). Kľúč oddielu určuje, do ktorého oddielu/úlomku by mal byť riadok umiestnený, a stĺpce zoskupovania označujú, ako by mali byť údaje usporiadané v aktuálnom zlomku.

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 organizuje dáta do databáz (Database) (podobne ako Keyspace v Cassandra), kde sú kolekcie (podobne ako tabuľky), ktoré obsahujú dokumenty (podobne ako riadky v tabuľke). V MongoDB v podstate nie je potrebné definovať počiatočnú schému. Tím "používať databázu", zobrazený nižšie, vytvorí inštanciu databázy pri prvom volaní a zmení kontext pre novovytvorenú databázu. Dokonca ani kolekcie nemusia byť vytvorené explicitne, vytvoria sa automaticky, jednoducho keď pridáte prvý dokument do novej kolekcie. Všimnite si, že MongoDB štandardne používa testovaciu databázu, takže každá operácia na úrovni kolekcie bez zadania konkrétnej databázy sa na nej štandardne spustí.

use myNewDatabase;

Získanie informácií o stole
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;

Zadávanie údajov do tabuľky
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

Celkový výraz INSERT v Cassandre vyzerá veľmi podobne ako v PostgreSQL. Je tu však jeden veľký rozdiel v sémantike. V Cassandre INSERT je vlastne operácia UPSERT, kde sa posledné hodnoty pridajú do riadku, ak riadok už existuje.

Zadávanie údajov je podobné ako v PostgreSQL INSERT nad

.

MongoDB

Aj keď je MongoDB databáza NoSQL ako Cassandra, jej operácia vkladania nemá nič spoločné so sémantickým správaním Cassandry. V MongoDB vložiť () nemá príležitosti UPSERT, čo ho robí podobným PostgreSQL. Pridávanie predvolených údajov bez _idspecified spôsobí pridanie nového dokumentu do zbierky.

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

Tabuľkový dotaz

Snáď najvýznamnejším rozdielom medzi SQL a NoSQL z hľadiska konštrukcie dotazov je použitý jazyk FROM и WHERE. SQL umožňuje po výraze FROM vyberte viacero tabuliek a vyjadrite sa pomocou WHERE môže mať akúkoľvek zložitosť (vrátane operácií JOIN medzi stolmi). NoSQL má však tendenciu ukladať prísne obmedzenia FROMa pracovať iba s jednou špecifikovanou tabuľkou a v WHERE, primárny kľúč musí byť vždy špecifikovaný. To súvisí s výkonom NoSQL, o ktorom sme hovorili skôr. Táto túžba vedie ku každému možnému zníženiu akejkoľvek interakcie medzi tabuľkami a kľúčmi. Môže spôsobiť veľké oneskorenie v medziuzlovej komunikácii pri odpovedi na požiadavku, a preto je lepšie sa mu vo všeobecnosti vyhnúť. Napríklad Cassandra vyžaduje, aby boli dotazy obmedzené na určitých operátorov (iba =, IN, <, >, =>, <=) na kľúčoch oddielov, okrem prípadu, keď požadujete sekundárny index (tu je povolený iba operátor =).

PostgreSQL

Nižšie sú uvedené tri príklady dotazov, ktoré možno jednoducho vykonať pomocou databázy SQL.

  • Zobraziť všetky skladby od interpreta;
  • Zobraziť všetky skladby od interpreta, ktoré zodpovedajú prvej časti názvu;
  • Zobraziť všetky skladby od interpreta, ktoré majú v názve určité slovo a majú cenu nižšiu ako 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

Z vyššie uvedených dopytov PostgreSQL bude v Cassandre fungovať bez zmeny iba prvý, pretože operátor LIKE nemožno použiť na zhlukovanie stĺpcov ako napr SongTitle. V tomto prípade sú povolené iba operátori = и 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

Ako je uvedené v predchádzajúcich príkladoch, hlavná metóda vytvárania dotazov v MongoDB je db.collection.find(). Táto metóda explicitne obsahuje názov kolekcie (music v príklade nižšie), takže dopytovanie viacerých kolekcií je zakázané.

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

Čítanie všetkých riadkov tabuľky

Čítanie všetkých riadkov je jednoducho špeciálny prípad vzoru dotazu, na ktorý sme sa pozreli skôr.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Podobne ako v príklade PostgreSQL vyššie.

MongoDB

db.music.find( {} );

Úprava údajov v tabuľke

PostgreSQL

PostgreSQL poskytuje pokyny UPDATE na zmenu údajov. Nemá žiadne príležitosti UPSERT, takže tento príkaz zlyhá, ak riadok už nie je v databáze.

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

Cassandra

Cassandra má UPDATE podobne ako PostgreSQL. UPDATE má rovnakú sémantiku UPSERT, podobný INSERT.

Podobne ako v príklade PostgreSQL vyššie.

MongoDB
Operácie aktualizácia () v MongoDB môže úplne aktualizovať existujúci dokument alebo aktualizovať iba určité polia. V predvolenom nastavení aktualizuje iba jeden dokument so zakázanou sémantikou UPSERT. Aktualizácia viacerých dokumentov a podobné správanie UPSERT možno použiť nastavením ďalších príznakov pre operáciu. Napríklad v nižšie uvedenom príklade sa žáner konkrétneho interpreta aktualizuje na základe jeho skladby.

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

Odstránenie údajov z tabuľky

PostgreSQL

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

Cassandra

Podobne ako v príklade PostgreSQL vyššie.

MongoDB

MongoDB má dva typy operácií na odstránenie dokumentov − deleteOne() /deleteMany() и odstrániť (). Oba typy vymažú dokumenty, ale vrátia iné výsledky.

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

Odstránenie tabuľky

PostgreSQL

DROP TABLE Music;

Cassandra

Podobne ako v príklade PostgreSQL vyššie.

MongoDB

db.music.drop();

Záver

Debata o výbere medzi SQL a NoSQL zúri už viac ako 10 rokov. V tejto diskusii existujú dva hlavné aspekty: architektúra databázového stroja (monolitická, transakčná SQL vs distribuovaná, netransakčná NoSQL) a prístup k návrhu databázy (modelovanie vašich údajov v SQL verzus modelovanie vašich dopytov v NoSQL).

S distribuovanou transakčnou databázou, ako je YugaByte DB, možno ľahko ukončiť diskusiu o architektúre databázy. Keďže objemy údajov sú väčšie ako objemy, ktoré je možné zapísať do jedného uzla, je nevyhnutná plne distribuovaná architektúra, ktorá podporuje lineárnu škálovateľnosť zápisu s automatickým zdieľaním/opätovným vyvažovaním.

Okrem toho, ako je uvedené v jednom z článkov Google CloudTransakčné, silne konzistentné architektúry sa teraz viac používajú na zabezpečenie lepšej agilnosti vývoja ako netransakčné, nakoniec konzistentné architektúry.

Keď sa vrátime k diskusii o návrhu databázy, je spravodlivé povedať, že oba prístupy k návrhu (SQL a NoSQL) sú potrebné pre akúkoľvek komplexnú aplikáciu v reálnom svete. Prístup „modelovania údajov“ SQL umožňuje vývojárom ľahšie splniť meniace sa obchodné požiadavky, zatiaľ čo prístup „modelovania dopytov“ NoSQL umožňuje tým istým vývojárom pracovať s veľkými objemami údajov s nízkou latenciou a vysokou priepustnosťou. Z tohto dôvodu YugaByte DB poskytuje SQL a NoSQL API v spoločnom jadre, namiesto toho, aby podporoval jeden z prístupov. Okrem toho, poskytnutím kompatibility s populárnymi databázovými jazykmi vrátane PostgreSQL a Cassandra, YugaByte DB zaisťuje, že vývojári sa nemusia učiť ďalší jazyk, aby mohli pracovať s distribuovaným, vysoko konzistentným databázovým strojom.

V tomto článku sme sa pozreli na to, ako sa základy návrhu databázy líšia medzi PostgreSQL, Cassandrou a MongoDB. V budúcich článkoch sa ponoríme do pokročilých konceptov dizajnu, ako sú indexy, transakcie, JOINy, TTL direktívy a JSON dokumenty.

Prajeme vám pekný zvyšok víkendu a pozývame vás bezplatný webinár, ktorá sa uskutoční 14. mája.

Zdroj: hab.com

Pridať komentár