Mélanger SQL et NoSQL avec MariaDB et MongoDB

Supposons que vous ayez une application développée en Node.js (ou n’importe quel autre plateforme). Cette application se connecte à une base de données MongoDB (NoSQL) pour stocker des notations sur les livres (nombre d’étoiles attribuées et un commentaire). Supposons également que vous ayez une autre application développée en Java (ou Python, C#, TypeScript… n’importe quoi). Cette application se connecte à une base de données MariaDB (SQL, relationnelle) pour gérer un catalogue de livres (titre, année de publication, nombre de pages).

On vous demande de créer un rapport qui affiche le titre et les informations de notation pour chaque livre. Notez que la base de données MongoDB ne contient pas le titre des livres, et la base de données relationnelle ne contient pas les notations. Nous devons mélanger des données créées par une application NoSQL avec des données créées par une application SQL.

A common approach to this is to query both databases independently (using different data sources) and process the data to match by, for example, ISBN (the id of a book) and put the combined information in a new object. This needs to be done in a programming language like Java, TypeScript, C#, Python, or any other imperative programming language that is able to connect to both databases.

A polyglot application

Cette approche fonctionne. Cependant, joindre les données est une tâche pour une base de données. Elles sont conçues pour ce genre d’opération de données. De plus, avec cette approche, l’application SQL n’est plus une application uniquement SQL ; elle devient une application polyglotte, ce qui augmente la complexité, rendant la maintenance plus difficile.

Avec un proxy de base de données comme MaxScale, vous pouvez joindre ces données au niveau de la base de données en utilisant le meilleur langage pour les données — SQL. Votre application SQL n’a pas besoin de devenir polyglotte.

Bien que cela nécessite un élément supplémentaire dans l’infrastructure, vous bénéficiez également de toutes les fonctionnalités qu’un proxy de base de données a à offrir. Des choses telles que la bascule automatique, masquage de données transparent, isolement de topologie, les caches, filtres de sécurité, et plus encore.

MaxScale est un puissant proxy de base de données intelligent qui comprend à la fois SQL et NoSQL. Il comprend également Kafka (pour la CDC ou l’ingestion de données), mais c’est un sujet pour une autre occasion. En bref, avec MaxScale, vous pouvez connecter votre application NoSQL à une base de données relationnelle entièrement conforme aux ACID bases de données relationnelles et stocker les données juste là à côté des tables que d’autres applications SQL utilisent.

MaxScale permet à une application SQL de consommer des données NoSQL.

Essayons cette dernière approche dans une expérience rapide et facile à suivre avec MaxScale. Vous aurez besoin des éléments suivants installés sur votre ordinateur:

Configuration de la base de données MariaDB

En utilisant un éditeur de texte simple, créez un nouveau fichier et enregistrez-le avec le nom docker-compose.yml. Le fichier devrait contenir ce qui suit:

YAML

 

version: "3.9"
services:
  mariadb:
    image: alejandrodu/mariadb
    environment:
      - MARIADB_CREATE_DATABASE=demo
      - MARIADB_CREATE_USER=user:Password123!
      - MARIADB_CREATE_MAXSCALE_USER=maxscale_user:MaxScalePassword123!


  maxscale:
    image: alejandrodu/mariadb-maxscale
    command: --admin_host 0.0.0.0 --admin_secure_gui false
    ports:
      - "3306:4000"
      - "27017:27017"
      - "8989:8989"
    environment:
      - MAXSCALE_USER=maxscale_user:MaxScalePassword123!
      - MARIADB_HOST_1=mariadb 3306
      - MAXSCALE_CREATE_NOSQL_LISTENER=user:Password123!

Ceci est un fichier Docker Compose. Il décrit un ensemble de services à créer par Docker. Nous créons deux services (ou conteneurs) — un serveur de base de données MariaDB et un proxy de base de données MaxScale. Ils fonctionneront localement sur votre machine, mais dans les environnements de production, il est courant de les déployer sur des machines physiques distinctes. Gardez à l’esprit que ces images Docker ne conviennent pas pour la production ! Elles sont destinées à être adaptées pour des démonstrations rapides et des tests. Vous pouvez trouver le code source de ces images sur GitHub. Pour les images Docker officielles de MariaDB, rendez-vous sur la page MariaDB sur Docker Hub.

Le fichier Docker Compose précédent configure un serveur de base de données MariaDB avec une base de données (ou schéma ; ils sont synonymes dans MariaDB) appelée demo. Il crée également un nom d’utilisateur user avec le mot de passe Password123!. Cet utilisateur dispose des privilèges appropriés sur la base de données demo. Il existe un utilisateur supplémentaire avec le nom maxscale_user et le mot de passe MaxScalePassword123!. C’est l’utilisateur que le proxy de base de données MaxScale utilisera pour se connecter à la base de données MariaDB.

Le fichier Docker Compose configure également le proxy de base de données en désactivant HTTPS (ne faites pas cela en production !), en exposant un ensemble de ports (plus sur ce point dans un instant), et en configurant l’utilisateur de la base de données et l’emplacement du proxy MariaDB (généralement une adresse IP, mais ici nous pouvons utiliser le nom du conteneur précédemment défini dans le fichier Docker). La dernière ligne crée un écouteur NoSQL que nous utiliserons pour nous connecter en tant que client MongoDB sur le port par défaut (27017).

Pour démarrer les services (conteneurs) à l’aide de la ligne de commande, se déplacez dans le répertoire où vous avez enregistré le fichier Docker Compose et exécutez ce qui suit:

Shell

 

docker compose up -d

Après avoir téléchargé tout le logiciel et démarré les conteneurs, vous disposerez d’une base de données MariaDB et d’un proxy MaxScale, tous deux préconfigurés pour cette expérience.

Création d’une table SQL dans MariaDB

Connectons-nous à la base de données relationnelle. Dans la ligne de commande, exécutez ce qui suit :

Shell

 

mariadb-shell --dsn mariadb://user:'Password123!'@127.0.0.1

Vérifiez que vous pouvez voir la base de données demo:

MariaDB SQL

 

show databases;

Passer à la base de données demo:

MariaDB SQL

 

use demo;

Se connecter à une base de données avec MariaDB Shell.

Créer la table books:

MariaDB SQL

 

CREATE TABLE books(
  isbn VARCHAR(20) PRIMARY KEY,
  title VARCHAR(256),
  year INT
);

Insérer des données. Je vais utiliser le cliché d’insérer mes propres books:

MariaDB SQL

 

INSERT INTO books(title, isbn, year)
VALUES
  ("Vaadin 7 UI Design By Example", "978-1-78216-226-1", 2013),
  ("Data-Centric Applications with Vaadin 8", "978-1-78328-884-7", 2018),
  ("Practical Vaadin", "978-1-4842-7178-0", 2021);

Vérifier que les livres sont stockés dans la base de données en exécutant:

MariaDB SQL

 

SELECT * FROM books;

Insérer des données avec MariaDB Shell.

Créer une collection JSON dans MariaDB

Nous n’avons pas encore installé MongoDB, mais nous pouvons utiliser un client MongoDB (ou application) pour nous connecter et créer des collections et des documents comme si nous utilisions MongoDB, à ceci près que les données sont stockées dans une base de données relationnelle puissante, entièrement conforme ACID, et évolutive. Essayons cela!

Dans la ligne de commande, utilisez l’outil shell MongoDB pour vous connecter à la base de données MongoDB… attendez… c’est en fait la base de données MariaDB! Exécutez ce qui suit:

Shell

 

mongosh

Par défaut, cet outil essaie de se connecter à un serveur MongoDB (qui, encore une fois, se trouve être MariaDB cette fois) en cours d’exécution sur votre machine locale (127.0.0.1) en utilisant le port par défaut (20017). Si tout se passe bien, vous devriez être en mesure de voir la base de données demo listée lorsque vous exécutez la commande suivante:

Plain Text

 

show databases

Passer à la base de données demo:

Plain Text

 

use demo

Se connecter à MariaDB à l’aide de Mongo Shell.

Nous sommes connectés à une base de données relationnelle depuis un client non relationnel ! Créons la collection ratings et insérons quelques données dedans :

Plain Text

 

db.ratings.insertMany([
	{
		"isbn": "978-1-78216-226-1",
		"starts": 5,
		"comment": "A good resource for beginners who want to learn Vaadin"
	},
	{
		"isbn": "978-1-78328-884-7",
		"starts": 4,
		"comment": "Explains Vaadin in the context of other Java technologies"
	},
	{
		"isbn": "978-1-4842-7178-0",
		"starts": 5,
		"comment": "The best resource to learn web development with Java and Vaadin"
	}
])

Vérifions que les notes sont persistées dans la base de données :

Plain Text

 

db.ratings.find()

Interrogation d’une base de données MariaDB à l’aide de Mongo Shell.

Utilisation des fonctions JSON dans MariaDB

À ce stade, nous avons une seule base de données qui, de l’extérieur, ressemble à une base de données NoSQL (MongoDB) et une base de données relationnelle (MariaDB). Nous sommes en mesure de nous connecter à la même base de données et d’écrire et de lire des données à partir de clients MongoDB et de clients SQL. Toutes les données sont stockées dans MariaDB, nous pouvons donc utiliser SQL pour joindre des données provenant de clients MongoDB ou d’applications avec des données provenant de clients MariaDB ou d’applications. Explorons comment MaxScale stocke des données MongoDB (collections et documents) dans MariaDB.

Connectez-vous à la base de données à l’aide d’un client SQL tel que mariadb-shell, et affichez les tables dans le schéma de démonstration :

MariaDB SQL

 

show tables in demo;

Vous devriez voir les tables books et ratings listées. ratings a été créée en tant que collection MongoDB. MaxScale a traduit les commandes envoyées par le client MongoDB et a créé une table pour stocker les données dans une table. Voyons la structure de cette table :

MariaDB SQL

 

describe demo.ratings;

A NoSQL collection is stored as a MariaDB relational table.

La table ratings contient deux colonnes :

  1. id : l’ID objet.
  2. doc : le document au format JSON.

Si nous examinons le contenu de la table, nous constatons que toutes les données concernant les notes sont stockées dans la colonne doc au format JSON :

MariaDB SQL

 

SELECT doc FROM demo.ratings \G

Les documents NoSQL sont stockés dans une base de données MariaDB.

Revenons à notre objectif initial—afficher les titres des livres avec leurs informations de notation. Ce n’est pas le cas, mais supposons pour un instant que la table ratings est une table régulière avec les colonnes stars et comment. Si c’était le cas, joindre cette table avec la table books serait facile, et notre travail serait terminé :

MariaDB SQL

 

/* this doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings r
JOIN books b USING(isbn)

Revenons à la réalité. Nous devons convertir la colonne doc de la table ratings réelle en une expression relationnelle qui peut être utilisée comme nouvelle table dans la requête. Quelque chose comme ceci :

MariaDB SQL

 

/* this still doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings rt
JOIN ...something to convert rt.doc to a table... AS r
JOIN books b USING(isbn)

Ce quelque chose est la fonction JSON_TABLE . MariaDB inclut un ensemble complet de fonctions JSON pour manipuler les chaînes JSON. Nous utiliserons la fonction JSON_TABLE pour convertir la colonne doc en une forme relationnelle que nous pourrons utiliser pour effectuer des jointures SQL. La syntaxe générale de la fonction JSON_TABLE est la suivante :

MariaDB SQL

 

JSON_TABLE(json_document, context_path COLUMNS (
    column_definition_1,
    column_definition_2,
    ...
  )
) [AS] the_new_relational_table

Où :

  • json_document : une chaîne ou une expression qui renvoie les documents JSON à utiliser.
  • context_path: une expression JSON Path qui définit les nœuds à utiliser comme source des lignes.

Et les définitions de colonnes (column_definition_1, column_definition_2, etc…) ont la syntaxe suivante:

MariaDB SQL

 

new_column_name sql_type PATH path_in_the_json_doc [on_empty] [on_error]

Combinant ces connaissances, notre requête SQL ressemblerait à ceci:

MariaDB SQL

 

SELECT b.title, r.stars, r.comment
FROM ratings rt
JOIN JSON_TABLE(rt.doc, '$' COLUMNS(
    isbn VARCHAR(20) PATH '$.isbn',
    stars INT PATH '$.starts',
    comment TEXT PATH '$.comment'
  )
) AS r
JOIN books b USING(isbn);

Joindre des données NoSQL et SQL dans une seule requête SQL.

Nous aurions pu utiliser la valeur ISBN comme ObjectID MongoDB et, par conséquent, comme la colonne id dans la table ratings, mais je vais vous laisser cela en exercice (indice : utilisez _id au lieu de isbn lors de l’insertion de données à l’aide du client ou de l’application MongoDB).

A Word on Scalability

Il y a une idée fausse selon laquelle les bases de données relationnelles ne sont pas évolutives horizontalement (ajout de plus de nœuds) tandis que les bases de données NoSQL le sont. Mais les bases de données relationnelles évoluent sans sacrifier les propriétés ACID. MariaDB a plusieurs moteurs de stockage adaptés à différentes charges de travail. Par exemple, vous pouvez évoluer une base de données MariaDB en mettant en œuvre le sharding des données avec l’aide de Spider. Vous pouvez également utiliser une variété de moteurs de stockage pour gérer différentes charges de travail au niveau de la table. Les jointures entre moteurs sont possibles dans une seule requête SQL.

Combiner plusieurs moteurs de stockage dans une seule base de données logique MariaDB.

Une autre alternative plus moderne est SQL distribué avec MariaDB Xpand. Une base de données SQL distribuée apparaît comme une seule base de données relationnelle logique aux applications grâce au mécanisme de fragmentation transparente. Elle utilise une architecture shared-nothing qui permet de faire évoluer à la fois les opérations de lecture et d’écriture.

A distributed SQL database deployment.

Conclusion

Notre travail ici est terminé! Désormais, vos systèmes peuvent disposer d’une vue scalable 360 degrés de vos données conforme à ACID, indépendamment du fait qu’elles aient été créées par des applications SQL ou NoSQL. Il y a moins besoin de migrer vos applications de NoSQL vers SQL ou de transformer les applications SQL en polyglottes de bases de données. Si vous souhaitez en savoir plus sur les autres fonctionnalités de MaxScale, regardez cette vidéo ou consultez la documentation.

Source:
https://dzone.com/articles/mixing-sql-and-nosql-with-mariadb-and-mongodb