Principes fondamentaux de la conception de bases de données – Comparaison de PostgreSQL, Cassandra et MongoDB

Bonjour les amis. Avant de partir pour la deuxième partie des vacances de mai, nous partageons avec vous le matériel que nous avons traduit en prévision du lancement d'un nouveau stream au tarif "SGBD relationnel".

Principes fondamentaux de la conception de bases de données – Comparaison de PostgreSQL, Cassandra et MongoDB

Les développeurs d'applications passent beaucoup de temps à comparer plusieurs bases de données opérationnelles pour choisir celle qui convient le mieux à la charge de travail prévue. Les besoins peuvent inclure une modélisation simplifiée des données, des garanties transactionnelles, des performances de lecture/écriture, une mise à l'échelle horizontale et une tolérance aux pannes. Traditionnellement, le choix commence par la catégorie de base de données, SQL ou NoSQL, puisque chaque catégorie propose un ensemble clair de compromis. Des performances élevées en termes de faible latence et de débit élevé sont généralement considérées comme une exigence qui ne peut être compromise et sont donc essentielles pour toute base de données de l'échantillon.

Le but de cet article est d'aider les développeurs d'applications à faire le bon choix entre SQL et NoSQL dans le cadre de la modélisation des données applicatives. Nous examinerons une base de données SQL, à savoir PostgreSQL, et deux bases de données NoSQL, Cassandra et MongoDB, pour couvrir les bases de la conception de bases de données, telles que la création de tables, leur remplissage, la lecture des données d'une table et leur suppression. Dans le prochain article, nous examinerons certainement les index, les transactions, les JOIN, les directives TTL et la conception de bases de données basées sur JSON.

Quelle est la différence entre SQL et NoSQL ?

Les bases de données SQL augmentent la flexibilité des applications grâce aux garanties transactionnelles ACID, ainsi que leur capacité à interroger des données à l'aide de JOIN de manière inattendue, en plus des modèles de bases de données relationnelles normalisées existantes.

Compte tenu de leur architecture monolithique/à nœud unique et de l'utilisation d'un modèle de réplication maître-esclave pour la redondance, les bases de données SQL traditionnelles manquent de deux fonctionnalités importantes : l'évolutivité linéaire en écriture (c'est-à-dire la répartition automatique sur plusieurs nœuds) et la perte de données automatique/ nulle. Cela signifie que la quantité de données reçues ne peut pas dépasser le débit d'écriture maximal d'un seul nœud. De plus, certaines pertes temporaires de données doivent être prises en compte pour la tolérance aux pannes (dans une architecture non partagée). Ici, vous devez garder à l'esprit que les commits récents n'ont pas encore été reflétés dans la copie esclave. Aucune mise à jour avec temps d'arrêt n'est également difficile à réaliser dans les bases de données SQL.

Les bases de données NoSQL sont généralement distribuées par nature, c'est-à-dire dans ceux-ci, les données sont divisées en sections et réparties sur plusieurs nœuds. Ils nécessitent une dénormalisation. Cela signifie que les données saisies doivent également être copiées plusieurs fois pour répondre aux demandes spécifiques que vous envoyez. L'objectif global est d'obtenir des performances élevées en réduisant le nombre de fragments disponibles lors des lectures. Cela implique que NoSQL vous oblige à modéliser vos requêtes, tandis que SQL vous oblige à modéliser vos données.

NoSQL met l'accent sur l'obtention de hautes performances dans un cluster distribué et c'est la principale raison de nombreux compromis de conception de bases de données, notamment la perte des transactions ACID, des JOIN et des index secondaires globaux cohérents.

Il existe une opinion selon laquelle, bien que les bases de données NoSQL offrent une évolutivité d'écriture linéaire et une tolérance aux pannes élevée, la perte des garanties transactionnelles les rend inadaptées aux données critiques.

Le tableau suivant montre en quoi la modélisation des données dans NoSQL diffère de SQL.

Principes fondamentaux de la conception de bases de données – Comparaison de PostgreSQL, Cassandra et MongoDB

SQL et NoSQL : pourquoi les deux sont-ils nécessaires ?

Les applications réelles comptant un grand nombre d’utilisateurs, telles qu’Amazon.com, Netflix, Uber et Airbnb, sont chargées d’exécuter des tâches complexes de toutes sortes. Par exemple, une application de commerce électronique comme Amazon.com doit stocker des données légères et très sensibles telles que des informations sur les utilisateurs, les produits, les commandes, les factures, ainsi que des données lourdes mais moins sensibles telles que des avis sur les produits, des messages d'assistance, l'activité des utilisateurs. , avis et recommandations des utilisateurs. Naturellement, ces applications s'appuient sur au moins une base de données SQL ainsi qu'au moins une base de données NoSQL. Dans les systèmes interrégionaux et mondiaux, la base de données NoSQL fonctionne comme un cache géodistribué pour les données stockées dans une source fiable, la base de données SQL, fonctionnant dans n'importe quelle région.

Comment YugaByte DB combine-t-il SQL et NoSQL ?

Construit sur un moteur de stockage mixte orienté journaux, le partage automatique, la réplication par consensus distribuée fragmentée et les transactions distribuées ACID (inspirées de Google Spanner), YugaByte DB est la première base de données open source au monde qui est simultanément compatible NoSQL (Cassandra & Redis). ) et SQL (PostgreSQL). Comme le montre le tableau ci-dessous, YCQL, une API YugaByte DB compatible avec Cassandra, ajoute les concepts de transactions ACID simples et multi-clés et d'index secondaires globaux à l'API NoSQL, ouvrant ainsi la voie à l'ère des bases de données transactionnelles NoSQL. De plus, YCQL, une API YugaByte DB compatible avec PostgreSQL, ajoute les concepts de mise à l'échelle d'écriture linéaire et de basculement automatique à l'API SQL, apportant ainsi au monde les bases de données SQL distribuées. La base de données YugaByte DB étant intrinsèquement transactionnelle, l'API NoSQL peut désormais être utilisée dans le contexte de données critiques.

Principes fondamentaux de la conception de bases de données – Comparaison de PostgreSQL, Cassandra et MongoDB

Comme indiqué précédemment dans l'article "Présentation de YSQL : une API SQL distribuée compatible PostgreSQL pour YugaByte DB", le choix entre SQL ou NoSQL dans YugaByte DB dépend entièrement des caractéristiques de la charge de travail sous-jacente :

  • Si votre charge de travail principale est constituée d'opérations JOIN multi-clés, alors lorsque vous choisissez YSQL, sachez que vos clés peuvent être réparties sur plusieurs nœuds, ce qui entraîne une latence plus élevée et/ou un débit inférieur à celui de NoSQL.
  • Sinon, choisissez l'une des deux API NoSQL, en gardant à l'esprit que vous obtiendrez de meilleures performances grâce aux requêtes exécutées à partir d'un nœud à la fois. YugaByte DB peut servir de base de données opérationnelle unique pour de véritables applications complexes qui doivent gérer plusieurs charges de travail en même temps.

Le laboratoire de modélisation des données de la section suivante est basé sur les API de base de données YugaByte DB compatibles PostgreSQL et Cassandra, par opposition aux bases de données d'origine. Cette approche met l'accent sur la facilité d'interagir avec deux API différentes (sur deux ports différents) du même cluster de bases de données, par opposition à l'utilisation de clusters complètement indépendants de deux bases de données différentes.
Dans les sections suivantes, nous examinerons le laboratoire de modélisation de données pour illustrer les différences et certains des points communs des bases de données couvertes.

Laboratoire de modélisation de données

Installation de bases de données

Étant donné l'accent mis sur la conception de modèles de données (plutôt que sur des architectures de déploiement complexes), nous installerons les bases de données dans des conteneurs Docker sur la machine locale, puis interagirons avec elles à l'aide de leurs shells de ligne de commande respectifs.

Compatible PostgreSQL & Cassandra, base de données YugaByte DB

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 en ligne de commande

Connectons-nous aux bases de données à l'aide du shell de ligne de commande pour les API respectives.

PostgreSQL

psql est un shell de ligne de commande pour interagir avec PostgreSQL. Pour faciliter l'utilisation, YugaByte DB est livré avec psql directement dans le dossier bin.

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

Cassandra

sqlsh est un shell de ligne de commande permettant d'interagir avec Cassandra et ses bases de données compatibles via CQL (Cassandra Query Language). Pour faciliter l'utilisation, YugaByte DB est livré avec cqlsh dans le catalogue bin.
Notez que CQL a été inspiré par SQL et a des concepts similaires de tables, lignes, colonnes et index. Cependant, en tant que langage NoSQL, il ajoute un certain ensemble de restrictions, dont la plupart seront également abordées dans d'autres articles.

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

MongoDB

mongo est un shell de ligne de commande pour interagir avec MongoDB. Il se trouve dans le répertoire bin de l'installation de MongoDB.

docker exec -it my-mongo bash 
cd bin
mongo

Créer une table

Nous pouvons désormais interagir avec la base de données pour effectuer diverses opérations à l'aide de la ligne de commande. Commençons par créer un tableau qui stocke des informations sur les chansons écrites par différents artistes. Ces chansons peuvent faire partie d'un album. Les attributs facultatifs de la chanson sont également l’année de sortie, le prix, le genre et la note. Nous devons prendre en compte des attributs supplémentaires qui pourraient être nécessaires à l'avenir via le champ "tags". Il peut stocker des données semi-structurées sous forme de paires clé-valeur.

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

La création d'une table dans Cassandra est très similaire à PostgreSQL. L'une des principales différences est l'absence de contraintes d'intégrité (par exemple NOT NULL), mais cela relève de la responsabilité de l'application et non de la base de données NoSQL.. La clé primaire se compose d'une clé de partition (colonne Artiste dans l'exemple ci-dessous) et d'un ensemble de colonnes de clustering (colonne SongTitle dans l'exemple ci-dessous). La clé de partition détermine dans quelle partition/partition placer la ligne, et les colonnes de clustering indiquent comment les données doivent être organisées dans la partition actuelle.

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 organise les données dans des bases de données (Database) (similaires à Keyspace dans Cassandra), où se trouvent des collections (similaires à des tables) qui contiennent des documents (similaires aux lignes d'une table). Dans MongoDB, il n'est fondamentalement pas nécessaire de définir un schéma initial. Équipe "utiliser la base de données", illustré ci-dessous, instancie la base de données lors du premier appel et modifie le contexte de la base de données nouvellement créée. Même les collections n'ont pas besoin d'être créées explicitement, elles sont créées automatiquement, juste lorsque le premier document est ajouté à une nouvelle collection. Notez que MongoDB utilise une base de données de test par défaut, donc toute opération au niveau de la collection sans spécifier de base de données spécifique y sera effectuée par défaut.

use myNewDatabase;

Obtenir des informations sur une table
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;

Saisir des données dans un tableau
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 général, l'expression INSERT dans Cassandra ressemble beaucoup à celui de PostgreSQL. Cependant, il existe une grande différence au niveau sémantique. À Cassandre INSERT est en fait une opération UPSERT, où les dernières valeurs sont ajoutées à la chaîne, au cas où la chaîne existe déjà.

La saisie des données est similaire à PostgreSQL INSERT au-dessus

.

MongoDB

Même si MongoDB est une base de données NoSQL comme Cassandra, son opération de saisie de données n'a rien à voir avec le comportement sémantique de Cassandra. Dans MongoDB insérer() n'a aucune opportunité UPSERT, ce qui le rend similaire à PostgreSQL. Ajout de données par défaut sans _idspecified entraînera l'ajout d'un nouveau document à la collection.

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

Requête de table

La différence la plus significative entre SQL et NoSQL en termes de requêtes est peut-être l'utilisation de FROM и WHERE. SQL autorise après l'expression FROM sélectionnez plusieurs tables et une expression avec WHERE peut être de toute complexité (y compris les opérations JOIN entre les tableaux). Cependant, NoSQL a tendance à imposer une limite stricte à FROM, et travaillez avec une seule table spécifiée, et dans WHERE, la clé primaire doit toujours être spécifiée. Cela est dû à la volonté d'améliorer les performances de NoSQL, dont nous avons parlé plus tôt. Ce désir conduit à réduire autant que possible toute interaction entre tableaux croisés et touches croisées. Cela peut introduire un retard important dans la communication entre les nœuds lors de la réponse à une demande et il est donc préférable de l'éviter en principe. Par exemple, Cassandra exige que les requêtes soient limitées à certains opérateurs (uniquement autorisées =, IN, <, >, =>, <=) sur les clés de partition, sauf lors de l'interrogation d'un index secondaire (seul l'opérateur = est autorisé ici).

PostgreSQL

Vous trouverez ci-dessous trois exemples de requêtes pouvant facilement être exécutées par une base de données SQL.

  • Afficher toutes les chansons de l'artiste ;
  • Afficher toutes les chansons de l'artiste qui correspondent à la première partie du titre ;
  • Affichez toutes les chansons de l'artiste qui ont un certain mot dans le titre et dont le prix est inférieur à 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

Parmi les requêtes PostgreSQL répertoriées ci-dessus, seule la première fonctionnera inchangée dans Cassandra, car l'instruction LIKE ne peut pas être appliqué aux colonnes de clustering telles que SongTitle. Dans ce cas, seuls les opérateurs sont autorisés = и 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

Comme le montrent les exemples précédents, la principale méthode de création de requêtes dans MongoDB est db.collection.find(). Cette méthode contient explicitement le nom de la collection (music dans l'exemple ci-dessous), il est donc interdit d'interroger plusieurs collections.

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

Lire toutes les lignes d'un tableau

La lecture de toutes les lignes est simplement un cas particulier du modèle de requête que nous avons examiné précédemment.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Semblable à l'exemple PostgreSQL ci-dessus.

MongoDB

db.music.find( {} );

Modification de données dans un tableau

PostgreSQL

PostgreSQL fournit une instruction UPDATE pour modifier les données. Elle n'a aucune opportunité UPSERT, donc cette instruction échouera si la ligne n'est plus dans la base de données.

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

Cassandra

Cassandre a UPDATE similaire à PostgreSQL. UPDATE a la même sémantique UPSERT, comme INSERT.

Semblable à l'exemple PostgreSQL ci-dessus.

MongoDB
Opération mettre à jour () dans MongoDB, il peut mettre à jour complètement un document existant ou mettre à jour uniquement certains champs. Par défaut, il ne met à jour qu'un seul document avec la sémantique désactivée UPSERT. Actualiser plusieurs documents et comportement similaire UPSERT peut être appliqué en définissant des indicateurs supplémentaires pour l’opération. Comme par exemple dans l'exemple ci-dessous, le genre d'un artiste particulier est mis à jour par sa chanson.

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

Supprimer des données d'une table

PostgreSQL

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

Cassandra

Semblable à l'exemple PostgreSQL ci-dessus.

MongoDB

MongoDB propose deux types d'opérations pour supprimer des documents - supprimerUn() /supprimerBeaucoup() и retirer(). Les deux types suppriment des documents mais renvoient des résultats différents.

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

Supprimer un tableau

PostgreSQL

DROP TABLE Music;

Cassandra

Semblable à l'exemple PostgreSQL ci-dessus.

MongoDB

db.music.drop();

Conclusion

Le débat sur le choix entre SQL et NoSQL fait rage depuis plus de 10 ans. Il y a deux aspects principaux dans ce débat : l'architecture du moteur de base de données (SQL monolithique et transactionnel vs NoSQL distribué et non transactionnel) et l'approche de la conception de bases de données (modélisation des données en SQL vs modélisation de vos requêtes en NoSQL).

Avec une base de données transactionnelle distribuée telle que YugaByte DB, le débat sur l'architecture de la base de données peut être facilement dissipé. À mesure que les volumes de données deviennent plus importants que ce qui peut être écrit sur un seul nœud, une architecture entièrement distribuée prenant en charge l'évolutivité en écriture linéaire avec partitionnement/rééquilibrage automatique devient nécessaire.

En plus de ce qui a été dit dans l'un des articles Google Cloud, les architectures transactionnelles et fortement cohérentes sont désormais plus largement adoptées pour offrir une meilleure flexibilité de développement que les architectures non transactionnelles et finalement cohérentes.

Revenant à la discussion sur la conception de bases de données, il est juste de dire que les deux approches de conception (SQL et NoSQL) sont nécessaires pour toute application complexe du monde réel. L'approche de « modélisation des données » de SQL permet aux développeurs de répondre plus facilement aux exigences changeantes de l'entreprise, tandis que l'approche de « modélisation des requêtes » de NoSQL permet à ces mêmes développeurs de gérer de grandes quantités de données avec une faible latence et un débit élevé. C'est pour cette raison que YugaByte DB fournit des API SQL et NoSQL dans un noyau commun et ne préconise aucune des approches. De plus, en assurant la compatibilité avec les langages de bases de données populaires, notamment PostgreSQL et Cassandra, YugaByte DB garantit que les développeurs n'ont pas besoin d'apprendre un autre langage pour travailler avec un moteur de base de données distribué fortement cohérent.

Dans cet article, nous avons examiné en quoi les principes fondamentaux de conception de bases de données diffèrent entre PostgreSQL, Cassandra et MongoDB. Dans les articles suivants, nous aborderons les concepts de conception avancés tels que les index, les transactions, les JOIN, les directives TTL et les documents JSON.

Nous vous souhaitons une excellente fin de week-end et vous invitons à webinaire gratuitqui aura lieu le 14 mai.

Source: habr.com

Ajouter un commentaire