Het mengen van SQL en NoSQL met MariaDB en MongoDB

Stel dat je een applicatie hebt ontwikkeld in Node.js (of een ander platform). Deze applicatie verbindt zich met een MongoDB-database (NoSQL) om beoordelingen over boeken op te slaan (aantal sterren en een opmerking). Stel ook dat je een andere applicatie ontwikkeld hebt in Java (of Python, C#, TypeScript… wat dan ook). Deze applicatie verbindt zich met een MariaDB database (SQL, relationeel) om een catalogus van boeken te beheren (titel, publicatiejaar, aantal pagina’s).

Je wordt gevraagd om een rapport te maken dat de titel en beoordelingsinformatie voor elk boek weergeeft. Merk op dat de MongoDB-database de titel van de boeken niet bevat, en de relationele database bevat geen beoordelingen. We moeten gegevens die zijn gecreëerd door een NoSQL-applicatie mengen met gegevens die zijn gecreëerd door een SQL-applicatie.

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

Deze aanpak werkt. Echter, het samenvoegen van gegevens is een taak voor een database. Ze zijn hiervoor gebouwd. Ook met deze aanpak is de SQL-applicatie niet langer een SQL-enige applicatie; het wordt een database-polyglot, en dit vergroot de complexiteit, waardoor het moeilijker te onderhouden is.

Met een database proxy zoals MaxScale kun je deze gegevens op database niveau samenvoegen met de beste taal voor gegevens – SQL. Je SQL-applicatie hoeft niet een polyglot te worden.

Hoewel dit een extra element in de infrastructuur vereist, krijg je ook alle functionaliteit die een database proxy te bieden heeft. Denk aan zaken zoals automatisch failover, transparante gegevensmaskering, topologie-isolatie, caches, beveiligingsfilters en meer.

MaxScale is een krachtige, intelligente database proxy die zowel SQL als NoSQL begrijpt. Het begrijpt ook Kafka (voor CDC of gegevensinname), maar dat is een onderwerp voor een ander moment. Kort gezegd, met MaxScale kun je je NoSQL-toepassing verbinden met een volledig ACID-compatibele relationele database en de gegevens daar direct naast tabellen opslaan die andere SQL-toepassingen gebruiken.

MaxScale staat een SQL-toepassing toe om NoSQL-gegevens te consumeren.

Laten we deze laatste aanpak in een snelle en gemakkelijk te volgen experiment met MaxScale uitproberen. Je hebt het volgende op je computer geïnstalleerd nodig:

Het instellen van de MariaDB-Database

Gebruik een teksteditor zonder opmaak, maak een nieuw bestand aan en sla het op onder de naam docker-compose.yml. Het bestand zou het volgende moeten bevatten:

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!

Dit is een Docker Compose bestand. Het beschrijft een set diensten die door Docker moeten worden gemaakt. We maken twee diensten (of containers) aan — een MariaDB-databaseserver en een MaxScale-databaseproxy. Ze zullen lokaal op je machine draaien, maar in productieomgevingen is het gebruikelijk om ze op afzonderlijke fysieke machines te implementeren. Houd er rekening mee dat deze Docker-installatiekopieën niet geschikt zijn voor productie! Ze zijn bedoeld om geschikt te zijn voor snelle demonstraties en tests. Je kunt de broncode voor deze installatiekopieën vinden op GitHub. Voor de officiële Docker-installatiekopieën van MariaDB, ga naar de MariaDB-pagina op Docker Hub.

Het vorige Docker Compose bestand configureert een MariaDB databaseserver met een database (of schema; ze zijn synoniemen in MariaDB) genaamd demo. Er wordt ook een gebruikersnaam user gemaakt met het wachtwoord Password123!. Deze gebruiker heeft geschikte rechten op de demo database. Er is een extra gebruiker met de naam maxscale_user en wachtwoord MaxScalePassword123!. Dit is de gebruiker die de MaxScale database proxy zal gebruiken om verbinding te maken met de MariaDB database.

Het Docker Compose bestand configureert ook de database proxy door HTTPS uit te schakelen (doe dit niet in productie!), een reeks poorten bloot te stellen (meer hierover in een moment), en de database gebruiker en locatie van de MariaDB database proxy te configureren (meestal een IP-adres, maar hier kunnen we de naam van de container gebruiken die eerder gedefinieerd is in het Docker bestand). De laatste regel creëert een NoSQL listener die we zullen gebruiken om als MongoDB-client te verbinden op de standaardpoort (27017).

Om de services (containers) te starten via de command line, ga naar de map waarin je het Docker Compose bestand hebt opgeslagen en voer het volgende uit:

Shell

 

docker compose up -d

Na het downloaden van alle software en het starten van de containers, heb je een MariaDB database en MaxScale proxy, beide vooraf geconfigureerd voor dit experiment.

Een SQL Tabel maken in MariaDB

Laten we verbinding maken met de relationele database. In de command line voer je het volgende uit:

Shell

 

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

Controleer of u de demo database kunt zien:

MariaDB SQL

 

show databases;

Schakel over naar de demo database:

MariaDB SQL

 

use demo;

Verbinding maken met een database met MariaDB Shell.

Maak de books tabel:

MariaDB SQL

 

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

Voeg wat gegevens toe. Ik ga de cliché gebruiken van het invoeren van mijn eigen boeken:

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

Controleer of de boeken in de database zijn opgeslagen door het volgende uit te voeren:

MariaDB SQL

 

SELECT * FROM books;

Gegevens invoegen met MariaDB Shell.

Een JSON Collection maken in MariaDB

We hebben MongoDB nog niet geïnstalleerd, toch kunnen we een MongoDB-client (of -applicatie) gebruiken om verbinding te maken en collecties en documenten te creëren alsof we MongoDB gebruiken, behalve dat de gegevens worden opgeslagen in een krachtige, volledig ACID-compatibele en schaalbare relationele database. Laten we dat proberen!

In de command line, gebruik de MongoDB shell tool om verbinding te maken met de MongoDB… wacht… het is eigenlijk de MariaDB database! Voer het volgende uit:

Shell

 

mongosh

Standaard probeert dit hulpmiddel verbinding te maken met een MongoDB-server (die, nogmaals, MariaDB is dit keer) die op uw lokale machine (127.0.0.1) draait met behulp van de standaard poort (20017). Als alles goed gaat, zou u de demo database moeten kunnen zien wanneer u het volgende commando uitvoert:

Plain Text

 

show databases

Schakel over naar de demo database:

Plain Text

 

use demo

Verbinding maken met MariaDB met Mongo Shell.

We zijn verbonden met een relationele database vanuit een niet-relationeel client! Laten we de ratings collectie aanmaken en wat gegevens inzetten:

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

Controleer of de ratings zijn bewaard in de database:

Plain Text

 

db.ratings.find()

Query’s uitvoeren op een MariaDB-database met behulp van Mongo Shell.

JSON-functies gebruiken in MariaDB

Op dit moment hebben we een enkele database die, van buitenaf, lijkt op een NoSQL (MongoDB) database en een relationele (MariaDB) database. We kunnen verbinding maken met dezelfde database en gegevens schrijven en lezen vanuit MongoDB-clients en SQL-clients. Alle gegevens worden opgeslagen in MariaDB, dus we kunnen SQL gebruiken om gegevens van MongoDB-clients of -toepassingen te koppelen aan gegevens van MariaDB-clients of -toepassingen. Laten we onderzoeken hoe MaxScale MariaDB gebruikt om MongoDB-gegevens (collecties en documenten) op te slaan.

Maak verbinding met de database met behulp van een SQL-client zoals mariadb-shell, en toon de tabellen in het demo-schema:

MariaDB SQL

 

show tables in demo;

U zou zowel de books als de ratings tabellen moeten zien. ratings Werd aangemaakt als een MongoDB collectie. MaxScale heeft de opdrachten die vanuit de MongoDB-client werden verzonden getransformeerd en een tabel aangemaakt om de gegevens in op te slaan. Laten we eens kijken naar de structuur van deze tabel:

MariaDB SQL

 

describe demo.ratings;

A NoSQL collection is stored as a MariaDB relational table.

De ratings tabel bevat twee kolommen:

  1. id: de object-ID.
  2. doc: het document in JSON formaat.

Als we de inhoud van de tabel bekijken, zien we dat alle gegevens over beoordelingen worden opgeslagen in de doc kolom in JSON-indeling:

MariaDB SQL

 

SELECT doc FROM demo.ratings \G

NoSQL-documenten worden opgeslagen in een MariaDB-database.

Laten we terugkeren naar ons oorspronkelijke doel—de boektitels met hun beoordelingsinformatie weergeven. Het volgende is niet het geval, maar stel even dat de ratings tabel een gewone tabel is met kolommen stars en comment. Als dat het geval zou zijn, zou het samenvoegen van deze tabel met de books tabel eenvoudig zijn en zou onze taak klaar zijn:

MariaDB SQL

 

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

Terug naar de werkelijkheid. We moeten de doc kolom van de werkelijke ratings tabel omzetten in een relationele expressie die kan worden gebruikt als een nieuwe tabel in de query. Zoiets als dit:

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)

Dat iets is de JSON_TABLE functie. MariaDB bevat een uitgebreid scala aan JSON-functies voor het manipuleren van JSON-tekststrings. We zullen de JSON_TABLE functie gebruiken om de doc kolom om te zetten in een relationeel formaat dat we kunnen gebruiken om SQL-samenvoegingen uit te voeren. De algemene syntaxis van de JSON_TABLE functie is als volgt:

MariaDB SQL

 

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

Waar:

  • json_document: een string of expressie die de JSON-documenten retourneert die moeten worden gebruikt.
  • context_path: een JSON Path expressie die de knooppunten definieert die worden gebruikt als bron voor de rijen.

En de kolomdefinities (column_definition_1, column_definition_2, etc…) hebben de volgende syntaxis:

MariaDB SQL

 

new_column_name sql_type PATH path_in_the_json_doc [on_empty] [on_error]

Met deze kennis zou onze SQL-query er als volgt uitzien:

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

Joining NoSQL en SQL-gegevens in één SQL-query.

We hadden de ISBN-waarde als MongoDB ObjectID kunnen gebruiken en daarom ook als de id kolom in de ratings tabel, maar ik zal dat aan jou overlaten als oefening (hint: gebruik _id in plaats van isbn bij het invoegen van gegevens met behulp van de MongoDB-client of app).

A Word on Scalability

Er bestaat het misverstand dat relationele databases niet horizontaal kunnen schalen (het toevoegen van meer knooppunten) terwijl NoSQL-databases dat wel kunnen. Maar relationele databases schalen zonder de ACID-eigenschappen op te offeren. MariaDB heeft meerdere opslagmotoren die zijn aangepast aan verschillende workloads. Bijvoorbeeld, je kunt een MariaDB-database schalen door data sharding te implementeren met behulp van Spider. Je kunt ook een verscheidenheid aan opslagmotoren gebruiken om verschillende workloads op basis van per tabel te behandelen. Cross-engine joins zijn mogelijk in één SQL-query.

Het combineren van meerdere opslagmotoren in één logische MariaDB-database.

Een andere modernere optie is ge­dis­tri­bu­teerde SQL met MariaDB Xpand. Een ge­dis­tri­bu­teerde SQL-database lijkt voor toepassingen als één logische relationele database door middel van transparante sharding. Het maakt gebruik van een shared-nothing-architectuur die zowel lezen als schrijven kan schalen.

A distributed SQL database deployment.

Conclusie

Ons werk is hier klaar! Nu kunnen uw systemen een ACID-compatibele schaalbare 360-gradenweergave van uw gegevens hebben, ongeacht of deze zijn gemaakt door SQL- of NoSQL-toepassingen. Er is minder behoefte om uw apps van NoSQL naar SQL te migreren of om SQL-apps databasepolyglotten te maken. Wilt u meer weten over andere functies in MaxScale? Bekijk deze video of bezoek de documentatie.

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