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
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.
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.
Ako už bolo uvedené v článku
- 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
docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres
Cassandra
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
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 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 FROM
a 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 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 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 −
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
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
Zdroj: hab.com