Hei venner. Før avreise til andre del av maiferien deler vi med deg materialet som vi oversatte i påvente av lanseringen av en ny strøm på kurset
Applikasjonsutviklere bruker mye tid på å sammenligne flere operasjonelle databaser for å velge den som passer best til den tiltenkte arbeidsmengden. Behov kan omfatte forenklet datamodellering, transaksjonsgarantier, lese-/skriveytelse, horisontal skalering og feiltoleranse. Tradisjonelt begynner valget med databasekategorien, SQL eller NoSQL, siden hver kategori presenterer et klart sett med avveininger. Høy ytelse når det gjelder lav ventetid og høy gjennomstrømning blir generelt sett på som et ikke-avveiningskrav og er derfor avgjørende for enhver prøvedatabase.
Hensikten med denne artikkelen er å hjelpe applikasjonsutviklere til å ta det riktige valget mellom SQL og NoSQL i sammenheng med applikasjonsdatamodellering. Vi skal se på én SQL-database, nemlig PostgreSQL, og to NoSQL-databaser, Cassandra og MongoDB, for å dekke det grunnleggende om databasedesign, for eksempel å lage tabeller, fylle dem, lese data fra en tabell og slette den. I den neste artikkelen skal vi se på indekser, transaksjoner, JOINs, TTL-direktiver og JSON-basert databasedesign.
Hva er forskjellen mellom SQL og NoSQL?
SQL-databaser øker applikasjonsfleksibiliteten gjennom ACID-transaksjonsgarantier, samt deres evne til å søke etter data ved hjelp av JOIN-er på uventede måter på toppen av eksisterende normaliserte relasjonsdatabasemodeller.
Gitt deres monolittiske/single-node-arkitektur og bruk av en master-slave-replikeringsmodell for redundans, mangler tradisjonelle SQL-databaser to viktige funksjoner - lineær skriveskalerbarhet (dvs. automatisk partisjonering over flere noder) og automatisk/null datatap. Dette betyr at mengden data som mottas ikke kan overstige maksimal skrivegjennomstrømning for en enkelt node. I tillegg må noe midlertidig datatap tas i betraktning i feiltoleranse (i en delt-ingenting-arkitektur). Her må du huske på at nylige forpliktelser ennå ikke har blitt reflektert i slavekopien. Oppdateringer uten nedetid er også vanskelig å oppnå i SQL-databaser.
NoSQL-databaser er vanligvis distribuert av natur, dvs. i dem er data delt inn i seksjoner og fordelt på flere noder. De krever denormalisering. Dette betyr at dataene som legges inn også må kopieres flere ganger for å svare på de spesifikke forespørslene du sender. Det overordnede målet er å oppnå høy ytelse ved å redusere antall tilgjengelige shards under lesing. Dette innebærer at NoSQL krever at du modellerer spørringene dine, mens SQL krever at du modellerer dataene dine.
NoSQL fokuserer på å oppnå høy ytelse i en distribuert klynge, og dette er den underliggende begrunnelsen for mange avveininger i databasedesign som inkluderer tap av ACID-transaksjoner, JOINs og konsistente globale sekundære indekser.
Det er et argument at mens NoSQL-databaser gir lineær skriveskalerbarhet og høy feiltoleranse, gjør tapet av transaksjonsgarantier dem uegnet for virksomhetskritiske data.
Tabellen nedenfor viser hvordan datamodellering i NoSQL skiller seg fra SQL.
SQL og NoSQL: Hvorfor trengs begge?
Virkelige applikasjoner med et stort antall brukere, som Amazon.com, Netflix, Uber og Airbnb, har i oppgave å utføre komplekse, mangefasetterte oppgaver. For eksempel må en e-handelsapplikasjon som Amazon.com lagre lette, høykritiske data som brukerinformasjon, produkter, bestillinger, fakturaer, sammen med tunge, mindre sensitive data som produktanmeldelser, støttemeldinger, brukeraktivitet, brukeranmeldelser og anbefalinger. Naturligvis er disse applikasjonene avhengige av minst én SQL-database sammen med minst én NoSQL-database. I tverrregionale og globale systemer fungerer en NoSQL-database som en geo-distribuert hurtigbuffer for data lagret i en pålitelig kilde-SQL-database som kjører i en enkelt region.
Hvordan kombinerer YugaByte DB SQL og NoSQL?
YugaByte DB er bygget på en loggorientert blandet lagringsmotor, auto-sharding, sharded distribuert konsensusreplikering og ACID-distribuerte transaksjoner (inspirert av Google Spanner), og er verdens første åpen kildekode-database som samtidig er kompatibel med NoSQL (Cassandra & Redis ) og SQL (PostgreSQL). Som vist i tabellen nedenfor, legger YCQL, YugaByte DB API kompatibel med Cassandra, konseptene med enkelt- og flernøkkel ACID-transaksjoner og globale sekundære indekser til NoSQL API, og innleder dermed æraen med transaksjonelle NoSQL-databaser. YCQL, YugaByte DB API som er kompatibel med PostgreSQL, legger i tillegg konseptene lineær skriveskalering og automatisk feiltoleranse til SQL API, og bringer distribuerte SQL-databaser til verden. Fordi YugaByte DB er transaksjonell i naturen, kan NoSQL API nå brukes i sammenheng med oppdragskritiske data.
Som tidligere nevnt i artikkelen
- Hvis den primære arbeidsbelastningen din er JOIN-operasjoner med flere nøkler, må du forstå at nøklene dine kan være fordelt på flere noder når du velger YSQL, noe som resulterer i høyere ventetid og/eller lavere gjennomstrømning enn NoSQL.
- Ellers velger du en av de to NoSQL API-ene, og husk at du vil få bedre ytelse som et resultat av spørringer servert fra en node om gangen. YugaByte DB kan fungere som en enkelt operasjonell database for komplekse applikasjoner i den virkelige verden som må håndtere flere arbeidsbelastninger samtidig.
Datamodelleringslaben i neste seksjon er basert på PostgreSQL og Cassandra API-kompatible YugaByte DB-databaser, i motsetning til native databaser. Denne tilnærmingen understreker det enkle å samhandle med to forskjellige APIer (på to forskjellige porter) i samme databaseklynge, i motsetning til å bruke helt uavhengige klynger av to forskjellige databaser.
I de følgende delene tar vi en titt på datamodelleringslaben for å illustrere forskjellene og noen av fellestrekkene til databasene som dekkes.
Datamodelleringslaboratorium
Database installasjon
Gitt vekten på datamodelldesign (i stedet for komplekse distribusjonsarkitekturer), vil vi installere databaser i Docker-beholdere på den lokale maskinen og deretter samhandle med dem ved å bruke deres respektive kommandolinjeskall.
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
Kommandolinjetilgang
La oss koble til databasene ved å bruke kommandolinjeskallet for de tilsvarende APIene.
PostgreSQL
docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres
Cassandra
cqlsh
i katalogen bin
.
Merk at CQL ble inspirert av SQL og har lignende konsepter for tabeller, rader, kolonner og indekser. Som et NoSQL-språk legger det imidlertid til et visst sett med begrensninger, de fleste av dem vil vi også dekke i andre artikler.
docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh
MongoDB
docker exec -it my-mongo bash
cd bin
mongo
Lag en tabell
Nå kan vi samhandle med databasen for å utføre ulike operasjoner ved hjelp av kommandolinjen. La oss starte med å lage en tabell som lagrer informasjon om sanger skrevet av forskjellige artister. Disse sangene kan være en del av et album. Valgfrie attributter for en sang er også utgivelsesår, pris, sjanger og vurdering. Vi må gjøre rede for ytterligere attributter som kan være nødvendig i fremtiden gjennom "tags"-feltet. Den kan lagre semistrukturerte data i form av nøkkelverdi-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
Å lage en tabell i Cassandra er veldig lik PostgreSQL. En av hovedforskjellene er mangelen på integritetsbegrensninger (f.eks. IKKE NULL), men dette er applikasjonens ansvar, ikke NoSQL-databasen. Primærnøkkelen består av en partisjonsnøkkel (Artist-kolonnen i eksemplet nedenfor) og et sett med klyngekolonner (SongTitle-kolonnen i eksemplet nedenfor). Partisjonsnøkkelen bestemmer hvilken partisjon/shard raden skal plasseres i, og klyngekolonnene angir hvordan dataene skal organiseres innenfor gjeldende 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) (ligner Keyspace i Cassandra), der det er samlinger (ligner på tabeller) som inneholder Dokumenter (ligner rader i en tabell). I MongoDB er det i utgangspunktet ikke nødvendig å definere et innledende skjema. Team "bruk database", vist nedenfor, instansierer databasen ved det første anropet og endrer konteksten for den nyopprettede databasen. Selv samlinger trenger ikke å opprettes eksplisitt; de opprettes automatisk, ganske enkelt når du legger til det første dokumentet i en ny samling. Merk at MongoDB bruker testdatabasen som standard, så enhver operasjon på samlingsnivå uten å spesifisere en spesifikk database vil kjøre på den som standard.
use myNewDatabase;
Få informasjon om en tabell
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;
Legge inn data i en tabell
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
Helhetsuttrykk INSERT
i Cassandra ser veldig ut som det i PostgreSQL. Det er imidlertid én stor forskjell i semantikk. I Cassandra INSERT
er faktisk en operasjon UPSERT
, hvor de siste verdiene legges til raden hvis raden allerede eksisterer.
Dataregistrering ligner på PostgreSQL
INSERT
ovenfor
.
MongoDB
Selv om MongoDB er en NoSQL-database som Cassandra, har innsettingsoperasjonen ingenting til felles med den semantiske oppførselen til Cassandra. I MongoDB UPSERT
, som gjør den lik PostgreSQL. Legger til standarddata uten _idspecified
vil føre til at et nytt dokument legges 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"
}
}
);
Tabellspørring
Den kanskje viktigste forskjellen mellom SQL og NoSQL når det gjelder spørringskonstruksjon er språket som brukes FROM
и WHERE
. SQL tillater etter uttrykk FROM
velg flere tabeller, og uttrykk med WHERE
kan være av hvilken som helst kompleksitet (inkludert operasjoner JOIN
mellom bordene). NoSQL har imidlertid en tendens til å pålegge en alvorlig begrensning på FROM
, og fungerer bare med én spesifisert tabell, og i WHERE
, må primærnøkkelen alltid spesifiseres. Dette knytter seg til NoSQL-ytelsespushet vi snakket om tidligere. Dette ønsket fører til enhver mulig reduksjon i enhver interaksjon på tvers av tabeller og nøkkelnøkler. Det kan introdusere en stor forsinkelse i kommunikasjon mellom noder når du svarer på en forespørsel, og er derfor best å unngå generelt. For eksempel krever Cassandra at forespørsler er begrenset til visse operatører (kun =, IN, <, >, =>, <=
) på partisjonsnøkler, bortsett fra når du ber om en sekundær indeks (bare =-operatøren er tillatt her).
PostgreSQL
Nedenfor er tre eksempler på spørringer som enkelt kan utføres av en SQL-database.
- Vis alle sanger av en artist;
- Vis alle sangene av artisten som samsvarer med den første delen av tittelen;
- Vis alle sanger av en artist som har et bestemt ord i tittelen og har en pris 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
Av PostgreSQL-spørringene som er oppført ovenfor, vil bare den første fungere uendret i Cassandra, siden operatøren LIKE
kan ikke brukes på klyngekolonner som f.eks SongTitle
. I dette tilfellet er kun operatører tillatt =
и 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 eksemplene, er hovedmetoden for å lage spørringer i MongoDB music
i eksemplet nedenfor), så det er forbudt å søke etter flere samlinger.
db.music.find( {
artist: "No One You Know"
}
);
db.music.find( {
artist: "No One You Know",
songTitle: /Call/
}
);
Leser alle rader i en tabell
Å lese alle rader er ganske enkelt et spesialtilfelle av spørringsmønsteret vi så på tidligere.
PostgreSQL
SELECT *
FROM Music;
Cassandra
Ligner på PostgreSQL-eksemplet ovenfor.
MongoDB
db.music.find( {} );
Redigering av data i en tabell
PostgreSQL
PostgreSQL gir instruksjoner UPDATE
å endre data. Hun har ingen muligheter UPSERT
, så denne setningen vil mislykkes hvis raden ikke lenger er i databasen.
UPDATE Music
SET Genre = 'Disco'
WHERE Artist = 'The Acme Band' AND SongTitle = 'Still In Love';
Cassandra
Cassandra har UPDATE
ligner på PostgreSQL. UPDATE
har samme semantikk UPSERT
, lignende INSERT
.
Ligner på PostgreSQL-eksemplet ovenfor.
MongoDB
Operasjon UPSERT
. Oppdatering av flere dokumenter og lignende oppførsel UPSERT
kan brukes ved å sette flere flagg for operasjonen. For eksempel, i eksemplet nedenfor, oppdateres sjangeren til en spesifikk artist basert på sangen hans.
db.music.update(
{"artist": "The Acme Band"},
{
$set: {
"genre": "Disco"
}
},
{"multi": true, "upsert": true}
);
Fjerne data fra en tabell
PostgreSQL
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
Cassandra
Ligner på PostgreSQL-eksemplet ovenfor.
MongoDB
MongoDB har to typer operasjoner for å slette dokumenter −
db.music.deleteMany( {
artist: "The Acme Band"
}
);
Sletter en tabell
PostgreSQL
DROP TABLE Music;
Cassandra
Ligner på PostgreSQL-eksemplet ovenfor.
MongoDB
db.music.drop();
Konklusjon
Debatten om å velge mellom SQL og NoSQL har pågått i mer enn 10 år. Det er to hovedaspekter ved denne debatten: databasemotorarkitektur (monolitisk, transaksjonell SQL vs distribuert, ikke-transaksjonell NoSQL) og databasedesigntilnærming (modellering av dataene dine i SQL vs modellering av spørringene dine i NoSQL).
Med en distribuert transaksjonsdatabase som YugaByte DB, kan debatten om databasearkitektur lett legges til ro. Ettersom datavolumer blir større enn det som kan skrives til en enkelt node, blir det nødvendig med en fullt distribuert arkitektur som støtter lineær skriveskalerbarhet med automatisk sharding/rebalansering.
Dessuten, som det står i en av artiklene
Når vi kommer tilbake til diskusjonen om databasedesign, er det rimelig å si at begge designtilnærmingene (SQL og NoSQL) er nødvendige for enhver kompleks applikasjon i den virkelige verden. SQL "datamodellering"-tilnærmingen lar utviklere lettere møte endrede forretningskrav, mens NoSQL "query modeling"-tilnærmingen lar de samme utviklerne operere på store datavolumer med lav latens og høy gjennomstrømning. Det er av denne grunn at YugaByte DB tilbyr SQL og NoSQL APIer i en felles kjerne, i stedet for å fremme en av tilnærmingene. I tillegg, ved å tilby kompatibilitet med populære databasespråk, inkludert PostgreSQL og Cassandra, sikrer YugaByte DB at utviklere ikke trenger å lære et annet språk for å jobbe med en distribuert, svært konsistent databasemotor.
I denne artikkelen så vi på hvordan grunnleggende databasedesign skiller seg mellom PostgreSQL, Cassandra og MongoDB. I fremtidige artikler vil vi dykke ned i avanserte designkonsepter som indekser, transaksjoner, JOINs, TTL-direktiver og JSON-dokumenter.
Vi ønsker deg en fin helg og inviterer deg til
Kilde: www.habr.com