Hej venner. Inden vi tager afsted til anden del af majferien, deler vi det materiale med dig, som vi har oversat i forventning om lanceringen af en ny stream til den hastighed
Applikationsudviklere bruger meget tid på at sammenligne flere operationelle databaser for at vælge den, der fungerer bedst til deres tilsigtede arbejdsbyrde. Behovene kan omfatte forenklet datamodellering, transaktionsgarantier, læse-/skriveydelse, horisontal skalering og fejltolerance. Traditionelt begynder valget med kategorien database, SQL eller NoSQL, da hver kategori giver et klart sæt af afvejninger. Høj ydeevne i form af lav latens og høj gennemløb ses generelt som et krav, der ikke kan kompromitteres og er derfor afgørende for enhver database i prøven.
Formålet med denne artikel er at hjælpe applikationsudviklere med at træffe det rigtige valg mellem SQL og NoSQL i forbindelse med applikationsdatamodellering. Vi vil se på én SQL-database, nemlig PostgreSQL, og to NoSQL-databaser, Cassandra og MongoDB, for at dække det grundlæggende i databasedesign, såsom at oprette tabeller, udfylde dem, læse data fra en tabel og slette dem. I den næste artikel vil vi helt sikkert se på indekser, transaktioner, JOINs, TTL-direktiver og databasedesign baseret på JSON.
Hvad er forskellen mellem SQL og NoSQL?
SQL-databaser øger applikationsfleksibiliteten gennem ACID-transaktionsgarantier, såvel som deres evne til at forespørge data ved hjælp af JOINs på uventede måder oven på eksisterende normaliserede relationsdatabasemodeller.
På grund af deres monolitiske/single node-arkitektur og brug af en master-slave-replikeringsmodel til redundans, mangler traditionelle SQL-databaser to vigtige funktioner - lineær skriveskalerbarhed (dvs. automatisk opdeling på tværs af flere noder) og automatisk/nul datatab. Dette betyder, at mængden af modtaget data ikke kan overstige den maksimale skrivegennemstrømning for en enkelt node. Derudover skal der tages højde for et vist midlertidigt tab af data for fejltolerance (i en ikke-delt arkitektur). Her skal du huske på, at de seneste commits endnu ikke er afspejlet i slavekopien. Ingen nedetidsopdateringer er også svære at opnå i SQL-databaser.
NoSQL-databaser er typisk distribueret i naturen, dvs. i dem er dataene opdelt i sektioner og fordelt over flere noder. De kræver denormalisering. Det betyder, at de indtastede data også skal kopieres flere gange for at kunne besvare de specifikke forespørgsler, du sender. Det overordnede mål er at få høj ydeevne ved at reducere antallet af tilgængelige shards på læsetidspunktet. Dette indebærer, at NoSQL kræver, at du modellerer dine forespørgsler, mens SQL kræver, at du modellerer dine data.
NoSQL lægger vægt på at opnå høj ydeevne i en distribueret klynge, og dette er hovedrationalet for mange afvejninger i databasedesign, som inkluderer tab af ACID-transaktioner, JOINs og konsistente globale sekundære indekser.
Der er en opfattelse af, at selvom NoSQL-databaser giver lineær skriveskalerbarhed og høj fejltolerance, gør tabet af transaktionsgarantier dem uegnede til kritiske data.
Følgende tabel viser, hvordan datamodellering i NoSQL adskiller sig fra SQL.
SQL og NoSQL: Hvorfor er begge nødvendige?
Virkelige applikationer med et stort antal brugere, såsom Amazon.com, Netflix, Uber og Airbnb, er ansvarlige for at udføre komplekse opgaver af forskellig art. For eksempel skal en e-handelsapplikation som Amazon.com gemme letvægts, meget følsomme data såsom oplysninger om brugere, produkter, ordrer, fakturaer sammen med tunge, men mindre følsomme data såsom produktanmeldelser, supportmeddelelser. , brugeraktivitet , brugeranmeldelser og anbefalinger. Disse applikationer er naturligvis afhængige af mindst én SQL-database sammen med mindst én NoSQL-database. I interregionale og globale systemer fungerer NoSQL-databasen som en geo-distribueret cache for data, der er gemt i en pålidelig kilde, SQL-database, der opererer i en hvilken som helst region.
Hvordan kombinerer YugaByte DB SQL og NoSQL?
YugaByte DB er bygget på en log-orienteret mixed storage-motor, auto-sharding, sharded distribueret konsensusreplikering og ACID-distribuerede transaktioner (inspireret af Google Spanner) og er verdens første open source-database, der samtidigt er NoSQL (Cassandra & Redis) kompatibel. ) og SQL (PostgreSQL). Som vist i nedenstående tabel tilføjer YCQL, en YugaByte DB API, der er kompatibel med Cassandra, koncepterne med enkelt- og multi-nøgle ACID-transaktioner og globale sekundære indekser til NoSQL API, og indvarsler dermed æraen med transaktionelle NoSQL-databaser. YCQL, en YugaByte DB API, der er kompatibel med PostgreSQL, tilføjer derudover koncepterne lineær skriveskalering og automatisk failover til SQL API, hvilket bringer distribuerede SQL-databaser til verden. Da YugaByte DB-databasen i sagens natur er transaktionsbetonet, kan NoSQL API nu bruges i forbindelse med kritiske data.
Som tidligere nævnt i artiklen
- Hvis din primære arbejdsbyrde er JOIN-operationer med flere nøgler, skal du, når du vælger YSQL, være opmærksom på, at dine nøgler kan være spredt over flere noder, hvilket resulterer i højere latenstid og/eller lavere gennemløb end NoSQL.
- Ellers skal du vælge en af de to NoSQL API'er, idet du husker på, at du vil få bedre ydeevne som et resultat af forespørgsler, der serveres fra én node ad gangen. YugaByte DB kan fungere som en enkelt operationel database til virkelig komplekse applikationer, der skal håndtere flere arbejdsbelastninger på samme tid.
Datamodelleringslaboratoriet i næste afsnit er baseret på PostgreSQL- og Cassandra-kompatible YugaByte DB-database-API'er i modsætning til de originale databaser. Denne tilgang understreger letheden ved at interagere med to forskellige API'er (på to forskellige porte) i den samme databaseklynge, i modsætning til at bruge fuldstændig uafhængige klynger af to forskellige databaser.
I de følgende afsnit tager vi et kig på Data Modeling Lab for at illustrere forskellen og nogle af de fælles træk ved de pågældende databaser.
Data Modeling Lab
Installation af databaser
I betragtning af fokus på datamodeldesign (i stedet for komplekse implementeringsarkitekturer), vil vi installere databaserne i Docker-containere på den lokale maskine og derefter interagere med dem ved hjælp af deres respektive kommandolinjeskaller.
PostgreSQL & Cassandra-kompatibel, YugaByte DB-database
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
Kommandolinjeadgang
Lad os oprette forbindelse til databaserne ved hjælp af kommandolinjeskallen for de respektive API'er.
PostgreSQL
docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres
Cassandra
cqlsh
i kataloget bin
.
Bemærk, at CQL var inspireret af SQL og har lignende koncepter for tabeller, rækker, kolonner og indekser. Men som et NoSQL-sprog tilføjer det et bestemt sæt begrænsninger, hvoraf de fleste også vil dække i andre artikler.
docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh
MongoDB
docker exec -it my-mongo bash
cd bin
mongo
Lav en tabel
Nu kan vi interagere med databasen for at udføre forskellige operationer ved hjælp af kommandolinjen. Lad os starte med at lave en tabel, der gemmer oplysninger om sange skrevet af forskellige kunstnere. Disse sange kan være en del af et album. Også valgfrie egenskaber for sangen er udgivelsesår, pris, genre og rating. Vi er nødt til at tage højde for yderligere attributter, der kan være nødvendige i fremtiden gennem feltet "tags". Det kan gemme semi-strukturerede data som nøgleværdi-par.
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
Oprettelse af en tabel i Cassandra ligner meget PostgreSQL. En af de vigtigste forskelle er fraværet af integritetsbegrænsninger (som NOT NULL), men dette er applikationens ansvar, ikke NoSQL-databasen.. Den primære nøgle består af en partitionsnøgle (Kunstner-kolonnen i eksemplet nedenfor) og et sæt klyngekolonner (SongTitle-kolonnen i eksemplet nedenfor). Partitionsnøglen bestemmer, hvilken partition/shard rækken skal placeres i, og klyngekolonnerne angiver, hvordan dataene skal organiseres i det aktuelle shard.
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 organiserer data i databaser (Database) (svarende til Keyspace i Cassandra), hvor der er samlinger (Samlinger) (svarende til tabeller), der indeholder dokumenter (Dokumenter) (svarende til rækker i en tabel). I MongoDB kræves der i princippet ingen indledende skemadefinition. Hold "brug database", vist nedenfor, instansierer databasen ved det første opkald og ændrer konteksten for den nyoprettede database. Selv samlinger behøver ikke at blive oprettet eksplicit, de oprettes automatisk, lige når det første dokument føjes til en ny samling. Bemærk, at MongoDB bruger en testdatabase som standard, så enhver operation på opsamlingsniveau uden at angive en specifik database vil blive udført i den som standard.
use myNewDatabase;
Få information om en tabel
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;
Indtastning af data i en tabel
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
Generelt udtrykket INSERT
i Cassandra ligner meget den i PostgreSQL. Der er dog én stor forskel i semantikken. I Cassandra INSERT
er faktisk en operation UPSERT
, hvor de seneste værdier tilføjes til strengen, hvis strengen allerede eksisterer.
Dataindtastning ligner PostgreSQL
INSERT
ovenfor
.
MongoDB
Selvom MongoDB er en NoSQL-database som Cassandra, har dens dataindtastningsoperation intet at gøre med Cassandras semantiske adfærd. I MongoDB UPSERT
, hvilket gør det ligner PostgreSQL. Tilføjelse af standarddata uden _idspecified
vil resultere i, at et nyt dokument tilføjes til samlingen.
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"
}
}
);
Tabelforespørgsel
Den måske vigtigste forskel mellem SQL og NoSQL med hensyn til forespørgsel er brugen af FROM
и WHERE
. SQL tillader efter udtryk FROM
vælg flere tabeller, og et udtryk med WHERE
kan være af enhver kompleksitet (inklusive operationer JOIN
mellem borde). NoSQL har dog en tendens til at sætte en hård grænse for FROM
, og arbejde med kun én specificeret tabel, og i WHERE
, skal den primære nøgle altid angives. Dette skyldes ønsket om at forbedre ydeevnen af NoSQL, som vi talte om tidligere. Dette ønske fører til enhver mulig reduktion af enhver krydsfane- og krydsnøgleinteraktion. Det kan introducere en stor forsinkelse i kommunikationen mellem knudepunkter, når man svarer på en anmodning, og undgås derfor i princippet bedst. For eksempel kræver Cassandra, at anmodninger er begrænset til visse operatører (kun tilladt =, IN, <, >, =>, <=
) på partitionsnøgler, undtagen ved forespørgsel efter et sekundært indeks (kun = operatoren er tilladt her).
PostgreSQL
Følgende er tre eksempler på forespørgsler, der nemt kan udføres af en SQL-database.
- Vis alle kunstnerens sange;
- Vis alle sange af kunstneren, der matcher den første del af titlen;
- Vis alle sange af kunstneren, der har et bestemt ord i titlen og har en pris på under 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
Af de ovenfor anførte PostgreSQL-forespørgsler vil kun den første fungere uændret i Cassandra, fordi sætningen LIKE
kan ikke anvendes på klyngekolonner som f.eks SongTitle
. I dette tilfælde er kun operatører tilladt =
и 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
Som vist i de foregående eksempler er hovedmetoden til at oprette forespørgsler i MongoDB music
i eksemplet nedenfor), så det er ikke tilladt at forespørge på flere samlinger.
db.music.find( {
artist: "No One You Know"
}
);
db.music.find( {
artist: "No One You Know",
songTitle: /Call/
}
);
Læsning af alle rækker i en tabel
At læse alle rækker er blot et specialtilfælde af det forespørgselsmønster, vi diskuterede tidligere.
PostgreSQL
SELECT *
FROM Music;
Cassandra
Svarende til PostgreSQL-eksemplet ovenfor.
MongoDB
db.music.find( {} );
Redigering af data i en tabel
PostgreSQL
PostgreSQL giver en erklæring UPDATE
at ændre data. Hun har ingen mulighed UPSERT
, så denne sætning vil mislykkes, hvis rækken ikke længere er i databasen.
UPDATE Music
SET Genre = 'Disco'
WHERE Artist = 'The Acme Band' AND SongTitle = 'Still In Love';
Cassandra
Cassandra har UPDATE
ligner PostgreSQL. UPDATE
har samme semantik UPSERT
, synes godt om INSERT
.
Svarende til PostgreSQL-eksemplet ovenfor.
MongoDB
Operation UPSERT
. Opdater flere dokumenter og lignende adfærd UPSERT
kan anvendes ved at indstille yderligere flag for operationen. Som for eksempel i eksemplet nedenfor, opdateres en bestemt kunstners genre af hans sang.
db.music.update(
{"artist": "The Acme Band"},
{
$set: {
"genre": "Disco"
}
},
{"multi": true, "upsert": true}
);
Fjernelse af data fra en tabel
PostgreSQL
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
Cassandra
Svarende til PostgreSQL-eksemplet ovenfor.
MongoDB
MongoDB har to typer operationer til sletning af dokumenter −
db.music.deleteMany( {
artist: "The Acme Band"
}
);
Sletning af en tabel
PostgreSQL
DROP TABLE Music;
Cassandra
Svarende til PostgreSQL-eksemplet ovenfor.
MongoDB
db.music.drop();
Konklusion
Debatten om valget mellem SQL og NoSQL har raset i over 10 år. Der er to hovedaspekter i denne debat: databasemotorens arkitektur (monolitisk, transaktionsbaseret SQL vs. distribueret, ikke-transaktionel NoSQL) og tilgangen til databasedesign (datamodellering i SQL vs. modellering af dine forespørgsler i NoSQL).
Med en distribueret transaktionsdatabase som YugaByte DB kan debatten om databasearkitektur let fordrives. Efterhånden som datamængderne bliver større end hvad der kan skrives til en enkelt node, bliver det nødvendigt med en fuldt distribueret arkitektur, der understøtter lineær skriveskalerbarhed med automatisk sharding/rebalancering.
Ud over hvad der blev sagt i en af artiklerne
For at vende tilbage til diskussionen om databasedesign, er det rimeligt at sige, at begge designtilgange (SQL og NoSQL) er nødvendige for enhver kompleks applikation i den virkelige verden. SQLs "datamodellering"-tilgang giver udviklere mulighed for lettere at imødekomme skiftende forretningskrav, mens NoSQL's "forespørgselsmodellering"-tilgang tillader de samme udviklere at håndtere store mængder data med lav latenstid og høj gennemstrømning. Det er af denne grund, at YugaByte DB leverer SQL og NoSQL API'er i en fælles kerne og ikke går ind for nogen af tilgangene. Ved at give kompatibilitet med populære databasesprog, herunder PostgreSQL og Cassandra, sikrer YugaByte DB desuden, at udviklere ikke behøver at lære et andet sprog for at arbejde med en distribueret, stærkt konsistent databasemotor.
I denne artikel så vi på, hvordan databasedesign fundamentals adskiller sig mellem PostgreSQL, Cassandra og MongoDB. I de følgende artikler vil vi dykke ned i avancerede designkoncepter såsom indekser, transaktioner, JOINs, TTL-direktiver og JSON-dokumenter.
Vi ønsker dig en god weekend og inviterer dig til
Kilde: www.habr.com