Fonaments del disseny de bases de dades: comparació de PostgreSQL, Cassandra i MongoDB

Hola amics. Abans de marxar a la segona part de les vacances de maig, compartim amb vosaltres el material que hem traduït en previsió del llançament d'un nou stream al ritme "DBMS relacional".

Fonaments del disseny de bases de dades: comparació de PostgreSQL, Cassandra i MongoDB

Els desenvolupadors d'aplicacions passen molt de temps comparant diverses bases de dades operatives per triar la que funcioni millor per a la seva càrrega de treball prevista. Les necessitats poden incloure modelatge de dades simplificat, garanties transaccionals, rendiment de lectura/escriptura, escalat horitzontal i tolerància a errors. Tradicionalment, l'elecció comença amb la categoria de base de dades, SQL o NoSQL, ja que cada categoria proporciona un conjunt clar de compensacions. L'alt rendiment en termes de baixa latència i alt rendiment es considera generalment un requisit que no es pot comprometre i, per tant, és essencial per a qualsevol base de dades de la mostra.

L'objectiu d'aquest article és ajudar els desenvolupadors d'aplicacions a prendre la decisió correcta entre SQL i NoSQL en el context del modelatge de dades d'aplicacions. Veurem una base de dades SQL, és a dir, PostgreSQL, i dues bases de dades NoSQL, Cassandra i MongoDB, per cobrir els conceptes bàsics del disseny de bases de dades, com ara crear taules, emplenar-les, llegir dades d'una taula i suprimir-les. En el següent article, definitivament mirarem els índexs, les transaccions, les JOIN, les directives TTL i el disseny de bases de dades basat en JSON.

Quina diferència hi ha entre SQL i NoSQL?

Les bases de dades SQL augmenten la flexibilitat de l'aplicació mitjançant les garanties transaccionals d'ACID, així com la seva capacitat per consultar dades mitjançant JOIN de maneres inesperades a més dels models de bases de dades relacionals normalitzats existents.

Atesa la seva arquitectura monolítica/d'un sol node i l'ús d'un model de replicació mestre-esclau per a la redundància, les bases de dades SQL tradicionals no tenen dues característiques importants: escalabilitat d'escriptura lineal (és a dir, divisió automàtica entre diversos nodes) i pèrdua de dades automàtica/zero. Això vol dir que la quantitat de dades rebudes no pot superar el rendiment màxim d'escriptura d'un sol node. A més, cal tenir en compte alguna pèrdua temporal de dades per a la tolerància a errors (en una arquitectura no compartida). Aquí heu de tenir en compte que les confirmacions recents encara no s'han reflectit a la còpia esclau. Les actualitzacions sense temps d'inactivitat també són difícils d'aconseguir a les bases de dades SQL.

Les bases de dades NoSQL solen estar distribuïdes per la naturalesa, és a dir. en ells, les dades es divideixen en seccions i es distribueixen en diversos nodes. Requereixen desnormalització. Això vol dir que les dades introduïdes també s'han de copiar diverses vegades per poder respondre a les sol·licituds concretes que envieu. L'objectiu general és aconseguir un alt rendiment reduint el nombre de fragments disponibles en temps de lectura. Això implica que NoSQL requereix que modeleu les vostres consultes, mentre que SQL requereix que modeleu les vostres dades.

NoSQL posa èmfasi en l'assoliment d'un alt rendiment en un clúster distribuït i aquesta és la raó principal de moltes compensacions de disseny de bases de dades, que inclouen la pèrdua de transaccions ACID, JOIN i índexs secundaris globals coherents.

Hi ha l'opinió que, tot i que les bases de dades NoSQL proporcionen escalabilitat d'escriptura lineal i una alta tolerància a errors, la pèrdua de garanties transaccionals les fa inadequades per a dades crítiques.

La taula següent mostra com es diferencia el modelatge de dades en NoSQL de l'SQL.

Fonaments del disseny de bases de dades: comparació de PostgreSQL, Cassandra i MongoDB

SQL i NoSQL: per què es necessiten tots dos?

Les aplicacions de la vida real amb un gran nombre d'usuaris, com Amazon.com, Netflix, Uber i Airbnb, s'encarreguen de realitzar tasques complexes de diversa índole. Per exemple, una aplicació de comerç electrònic com Amazon.com ha d'emmagatzemar dades lleugeres i molt sensibles, com ara informació sobre usuaris, productes, comandes, factures, juntament amb dades pesades però menys sensibles, com ara ressenyes de productes, missatges d'assistència, activitat dels usuaris. , comentaris i recomanacions dels usuaris. Naturalment, aquestes aplicacions es basen en almenys una base de dades SQL juntament amb almenys una base de dades NoSQL. En sistemes interregionals i globals, la base de dades NoSQL funciona com una memòria cau geodistribuïda per a les dades emmagatzemades en una font de confiança, una base de dades SQL, que opera a qualsevol regió.

Com combina YugaByte DB SQL i NoSQL?

Construït sobre un motor d'emmagatzematge mixt orientat al registre, fragmentació automàtica, replicació de consens distribuït fragmentat i transaccions distribuïdes ACID (inspirades en Google Spanner), YugaByte DB és la primera base de dades de codi obert del món que és simultàniament compatible amb NoSQL (Cassandra i Redis). ) i SQL (PostgreSQL). Tal com es mostra a la taula següent, YCQL, una API de base de dades de YugaByte compatible amb Cassandra, afegeix els conceptes de transaccions ACID de clau i multiclau i índexs secundaris globals a l'API NoSQL, marcant així l'era de les bases de dades NoSQL transaccionals. A més, YCQL, una API de base de dades de YugaByte compatible amb PostgreSQL, afegeix els conceptes d'escala d'escriptura lineal i migració automàtica per error a l'API SQL, portant les bases de dades SQL distribuïdes al món. Com que la base de dades YugaByte és inherentment transaccional, l'API NoSQL ara es pot utilitzar en el context de dades crítiques.

Fonaments del disseny de bases de dades: comparació de PostgreSQL, Cassandra i MongoDB

Com s'ha dit anteriorment a l'article "Presentem YSQL: una API SQL distribuïda compatible amb PostgreSQL per a YugaByte DB", l'elecció entre SQL o NoSQL a YugaByte DB depèn completament de les característiques de la càrrega de treball subjacent:

  • Si la vostra càrrega de treball principal són operacions JOIN de claus múltiples, aleshores, quan trieu YSQL, tingueu en compte que les vostres claus poden estar repartides entre diversos nodes, la qual cosa comporta una latència més alta i/o un rendiment inferior que NoSQL.
  • En cas contrari, trieu qualsevol de les dues API de NoSQL, tenint en compte que obtindreu un millor rendiment com a resultat de les consultes ateses des d'un node alhora. YugaByte DB pot servir com una base de dades operativa única per a aplicacions complexes reals que necessiten gestionar diverses càrregues de treball alhora.

El laboratori de modelització de dades de la secció següent es basa en les API de bases de dades YugaByte DB compatibles amb PostgreSQL i Cassandra, a diferència de les bases de dades originals. Aquest enfocament posa l'accent en la facilitat d'interaccionar amb dues API diferents (en dos ports diferents) del mateix clúster de bases de dades, en lloc d'utilitzar clústers completament independents de dues bases de dades diferents.
A les seccions següents, donarem una ullada al Laboratori de modelització de dades per il·lustrar la diferència i alguns dels punts comuns de les bases de dades en qüestió.

Laboratori de modelització de dades

Instal·lació de bases de dades

Tenint en compte l'enfocament en el disseny del model de dades (en lloc d'arquitectures de desplegament complexes), instal·larem les bases de dades als contenidors Docker a la màquina local i després interactuarem amb elles mitjançant les seves respectives intèrprets d'ordres de línia.

Compatible amb PostgreSQL i Cassandra, base de dades YugaByte

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

Accés a la línia d'ordres

Connectem-nos a les bases de dades mitjançant l'intèrpret d'ordres de la línia d'ordres per a les API respectives.

PostgreSQL

psql és un shell de línia d'ordres per interactuar amb PostgreSQL. Per facilitar-ne l'ús, YugaByte DB ve amb psql a la carpeta bin.

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

Cassandra

sqlsh és un shell de línia d'ordres per interactuar amb Cassandra i les seves bases de dades compatibles mitjançant CQL (Cassandra Query Language). Per facilitar-ne l'ús, inclou YugaByte DB cqlsh al catàleg bin.
Tingueu en compte que CQL es va inspirar en SQL i té conceptes similars de taules, files, columnes i índexs. Tanmateix, com a llenguatge NoSQL, afegeix un determinat conjunt de restriccions, la majoria de les quals també tractarem en altres articles.

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

MongoDB

mongo és un shell de línia d'ordres per interactuar amb MongoDB. Es pot trobar al directori bin de la instal·lació de MongoDB.

docker exec -it my-mongo bash 
cd bin
mongo

Crea una taula

Ara podem interactuar amb la base de dades per realitzar diverses operacions mitjançant la línia d'ordres. Comencem per crear una taula que emmagatzemi informació sobre cançons escrites per diferents artistes. Aquestes cançons poden formar part d'un àlbum. També els atributs opcionals de la cançó són l'any de llançament, el preu, el gènere i la qualificació. Hem de tenir en compte els atributs addicionals que poden ser necessaris en el futur mitjançant el camp "etiquetes". Pot emmagatzemar dades semiestructurades com a parells clau-valor.

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

Crear una taula a Cassandra és molt semblant a PostgreSQL. Una de les principals diferències és l'absència de restriccions d'integritat (com NOT NULL), però aquesta és responsabilitat de l'aplicació, no de la base de dades NoSQL.. La clau primària consta d'una clau de partició (columna Artista a l'exemple següent) i un conjunt de columnes agrupades (columna SongTitle a l'exemple següent). La clau de partició determina en quina partició/fragment s'ha de posar la fila, i les columnes de clúster indiquen com s'han d'organitzar les dades dins del fragment actual.

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 organitza les dades en bases de dades (base de dades) (similar a Keyspace a Cassandra), on hi ha col·leccions (col·leccions) (semblants a taules) que contenen documents (documents) (similars a les files d'una taula). A MongoDB, en principi, no es requereix cap definició d'esquema inicial. Equip "utilitza la base de dades", que es mostra a continuació, crea una instància de la base de dades a la primera trucada i canvia el context de la base de dades acabada de crear. Fins i tot les col·leccions no cal que es creïn explícitament, es creen automàticament, just quan s'afegeix el primer document a una nova col·lecció. Tingueu en compte que MongoDB utilitza una base de dades de prova de manera predeterminada, de manera que qualsevol operació de nivell de col·lecció sense especificar una base de dades específica s'hi farà de manera predeterminada.

use myNewDatabase;

Obtenció d'informació sobre una taula
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;

Introducció de dades en una taula
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

En general, l'expressió INSERT a Cassandra s'assembla molt al de PostgreSQL. Tanmateix, hi ha una gran diferència en la semàntica. En Cassandra INSERT en realitat és una operació UPSERT, on s'afegeixen els darrers valors a la cadena, en cas que la cadena ja existeix.

L'entrada de dades és similar a PostgreSQL INSERT dalt

.

MongoDB

Tot i que MongoDB és una base de dades NoSQL com Cassandra, la seva operació d'entrada de dades no té res a veure amb el comportament semàntic de Cassandra. A MongoDB insert () no té cap oportunitat UPSERT, que el fa semblant a PostgreSQL. Afegeix dades predeterminades sense _idspecified donarà lloc a un nou document que s'afegirà a la col·lecció.

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

Consulta de taula

Potser la diferència més significativa entre SQL i NoSQL en termes de consulta és l'ús de FROM и WHERE. SQL permet l'expressió posterior FROM seleccioneu diverses taules i una expressió amb WHERE pot ser de qualsevol complexitat (incloses les operacions JOIN entre taules). Tanmateix, NoSQL tendeix a imposar un límit dur FROM, i treballeu amb només una taula especificada i en WHERE, sempre s'ha d'especificar la clau primària. Això es deu a la voluntat de millorar el rendiment de NoSQL, del qual hem parlat anteriorment. Aquest desig condueix a tota la possible reducció de qualsevol interacció de tabulació i clau creuada. Pot introduir un gran retard en la comunicació entre nodes quan es respon a una sol·licitud i, per tant, és millor evitar-ho en general. Per exemple, Cassandra requereix que les sol·licituds estiguin restringides a determinats operadors (només es permeten =, IN, <, >, =>, <=) a les claus de partició, excepte quan es consulta un índex secundari (aquí només es permet l'operador =).

PostgreSQL

A continuació es mostren tres exemples de consultes que es poden executar fàcilment mitjançant una base de dades SQL.

  • Mostra totes les cançons de l'artista;
  • Mostra totes les cançons de l'artista que coincideixen amb la primera part del títol;
  • Mostra totes les cançons de l'artista que tenen una paraula determinada al títol i tenen un preu inferior a 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

De les consultes PostgreSQL enumerades anteriorment, només la primera funcionarà sense canvis a Cassandra, perquè la declaració LIKE no es pot aplicar a les columnes agrupades com ara SongTitle. En aquest cas, només es permeten els operadors = и 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

Com es mostra als exemples anteriors, el mètode principal per crear consultes a MongoDB és db.collection.find(). Aquest mètode conté explícitament el nom de la col·lecció (music a l'exemple següent), de manera que no es permet consultar diverses col·leccions.

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

Lectura de totes les files d'una taula

La lectura de totes les files és només un cas especial del patró de consulta que hem comentat anteriorment.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Similar a l'exemple de PostgreSQL anterior.

MongoDB

db.music.find( {} );

Edició de dades en una taula

PostgreSQL

PostgreSQL proporciona una declaració UPDATE per canviar les dades. Ella no té cap oportunitat UPSERT, de manera que aquesta declaració fallarà si la fila ja no es troba a la base de dades.

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

Cassandra

Cassandra té UPDATE similar a PostgreSQL. UPDATE té la mateixa semàntica UPSERT, M'agrada INSERT.

Similar a l'exemple de PostgreSQL anterior.

MongoDB
Operació update () a MongoDB pot actualitzar completament un document existent o actualitzar només determinats camps. Per defecte, només actualitza un document amb la semàntica desactivada UPSERT. Actualitzeu diversos documents i comportament similar UPSERT es pot aplicar establint indicadors addicionals per a l'operació. Com per exemple a l'exemple següent, el gènere d'un artista concret s'actualitza amb la seva cançó.

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

Eliminació de dades d'una taula

PostgreSQL

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

Cassandra

Similar a l'exemple de PostgreSQL anterior.

MongoDB

MongoDB té dos tipus d'operacions per esborrar documents − deleteOne() /deleteMany() и remove (). Tots dos tipus suprimeixen documents però retornen resultats diferents.

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

Esborrant una taula

PostgreSQL

DROP TABLE Music;

Cassandra

Similar a l'exemple de PostgreSQL anterior.

MongoDB

db.music.drop();

Conclusió

El debat sobre l'elecció entre SQL i NoSQL porta més de 10 anys. Hi ha dos aspectes principals en aquest debat: l'arquitectura del motor de bases de dades (monolític, SQL transaccional vs. NoSQL distribuït, no transaccional) i l'enfocament del disseny de bases de dades (modelació de dades en SQL vs. modelització de les vostres consultes en NoSQL).

Amb una base de dades transaccional distribuïda com YugaByte DB, el debat sobre l'arquitectura de la base de dades es pot dissipar fàcilment. A mesura que els volums de dades es fan més grans que el que es pot escriure en un sol node, es fa necessària una arquitectura totalment distribuïda que admeti escalabilitat d'escriptura lineal amb fragmentació/reequilibri automàtic.

A més del que es deia en un dels articles Google Cloud, les arquitectures transaccionals i molt consistents s'adopten ara de manera més àmplia per proporcionar una millor flexibilitat de desenvolupament que les arquitectures no transaccionals i, en última instància, coherents.

Tornant a la discussió del disseny de bases de dades, és just dir que els dos enfocaments de disseny (SQL i NoSQL) són necessaris per a qualsevol aplicació complexa del món real. L'enfocament de "modelació de dades" d'SQL permet als desenvolupadors complir amb més facilitat els requisits empresarials canviants, mentre que l'enfocament de "modelació de consultes" de NoSQL permet als mateixos desenvolupadors gestionar grans quantitats de dades amb baixa latència i alt rendiment. És per aquest motiu que YugaByte DB proporciona API SQL i NoSQL en un nucli comú i no defensa cap dels enfocaments. A més, en proporcionar compatibilitat amb els idiomes de bases de dades populars, inclosos PostgreSQL i Cassandra, YugaByte DB garanteix que els desenvolupadors no hagin d'aprendre un altre idioma per treballar amb un motor de bases de dades distribuït molt coherent.

En aquest article, vam analitzar com els fonaments del disseny de bases de dades difereixen entre PostgreSQL, Cassandra i MongoDB. En els articles següents, ens endinsarem en conceptes de disseny avançats com ara índexs, transaccions, JOIN, directives TTL i documents JSON.

Us desitgem un bon cap de setmana i us convidem seminari web gratuïtque tindrà lloc el 14 de maig.

Font: www.habr.com

Afegeix comentari