Supongamos que tienes una aplicación desarrollada en Node.js (o cualquier otra plataforma). Esta aplicación se conecta a una base de datos MongoDB (NoSQL) para almacenar calificaciones de libros (número de estrellas otorgadas y un comentario). Digamos también que tienes otra aplicación desarrollada en Java (o Python, C#, TypeScript… cualquier cosa). Esta aplicación se conecta a una base de datos MariaDB (SQL, relacional) para gestionar un catálogo de libros (título, año de publicación, número de páginas).
Te piden crear un informe que muestre el título y la información de calificación de cada libro. Tenga en cuenta que la base de datos MongoDB no contiene el título de los libros, y la base de datos relacional no contiene las calificaciones. Necesitamos combinar datos creados por una aplicación NoSQL con datos creados por una aplicación 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
Este enfoque funciona. Sin embargo, unir datos es un trabajo para una base de datos. Están diseñados para este tipo de operación de datos. Además, con este enfoque, la aplicación SQL ya no es una aplicación solo SQL; se convierte en una aplicación poliglota de bases de datos, lo que aumenta la complejidad y hace que sea más difícil de mantener.
Con un proxy de base de datos como MaxScale, puedes unir estos datos a nivel de base de datos utilizando el mejor lenguaje para los datos: SQL. Tu aplicación SQL no necesita convertirse en poliglota.
Aunque esto requiere un elemento adicional en la infraestructura, también obtienes toda la funcionalidad que un proxy de base de datos tiene para ofrecer. Cosas como failover automático, máscara de datos transparente, aislamiento de topología, cachés, filtros de seguridad y más.
MaxScale es un potente y inteligente proxy de base de datos que entiende tanto SQL como NoSQL. También entiende Kafka (para CDC o ingesta de datos), pero eso es un tema para otro momento. En resumen, con MaxScale, puedes conectar tu aplicación NoSQL a una base de datos relacional totalmente compatible con ACID relacional y almacenar los datos justo allí junto a las tablas que otros aplicaciones SQL utilizan.
MaxScale permite que una aplicación SQL consuma datos NoSQL.
Intentemos este último enfoque en un experimento rápido y fácil de seguir con MaxScale. Necesitarás lo siguiente instalado en tu computadora:
- Docker
- El
mariadb-shell
herramienta - El
mongosh
herramienta
Configuración de la Base de Datos MariaDB
Usando un editor de texto plano, crea un nuevo archivo y guárdalo con el nombre docker-compose.yml. El archivo debe contener lo siguiente:
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!
Este es un archivo Docker Compose. Describe un conjunto de servicios a crear por Docker. Estamos creando dos servicios (o contenedores) — un servidor de base de datos MariaDB y un proxy de base de datos MaxScale. Se ejecutarán localmente en tu máquina, pero en entornos de producción, es común desplegarlos en máquinas físicas separadas. Ten en cuenta que estas imágenes de Docker no son adecuadas para producción! Están destinadas a ser adecuadas para demostraciones rápidas y pruebas. Puedes encontrar el código fuente de estas imágenes en GitHub. Para las imágenes oficiales de Docker de MariaDB, dirígete a la página de MariaDB en Docker Hub.
El archivo Docker Compose anterior configura un servidor de base de datos MariaDB con una base de datos (o esquema; son sinónimos en MariaDB) llamada demo
. También crea un nombre de usuario user
con la contraseña Password123!
. Este usuario tiene privilegios adecuados en la base de datos demo
. Hay un usuario adicional con el nombre maxscale_user
y contraseña MaxScalePassword123!
. Este es el usuario que el proxy de base de datos MaxScale utilizará para conectarse al servidor de base de datos MariaDB.
El archivo Docker Compose también configura el proxy de la base de datos deshabilitando HTTPS (¡no hagas esto en producción!), exponiendo un conjunto de puertos (más sobre esto en un momento), y configurando el usuario de la base de datos y la ubicación del proxy de base de datos MariaDB (generalmente una dirección IP, pero aquí podemos usar el nombre del contenedor previamente definido en el archivo Docker). La última línea crea un escucha NoSQL que utilizaremos para conectarnos como cliente MongoDB en el puerto predeterminado (27017).
Para iniciar los servicios (contenedores) utilizando la línea de comandos, desplázate al directorio en el que guardaste el archivo Docker Compose y ejecuta lo siguiente:
docker compose up -d
Después de descargar todo el software y comenzar los contenedores, tendrás una base de datos MariaDB y un proxy MaxScale, ambos preconfigurados para esta experimentación.
Creando una Tabla SQL en MariaDB
Conectémonos a la base de datos relacional. En la línea de comandos, ejecuta lo siguiente:
mariadb-shell --dsn mariadb://user:'Password123!'@127.0.0.1
Verifica que puedas ver la base de datos demo
:
show databases;
Cambia a la base de datos demo
:
use demo;
Conectándose a una base de datos con MariaDB Shell.
Crea la tabla books
:
CREATE TABLE books(
isbn VARCHAR(20) PRIMARY KEY,
title VARCHAR(256),
year INT
);
Inserta algunos datos. Voy a usar el cliché de insertar mis propios libros:
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);
Verifica que los libros están almacenados en la base de datos ejecutando:
SELECT * FROM books;
Insertando datos con MariaDB Shell.
Creando una Colección JSON en MariaDB
Aún no hemos instalado MongoDB, pero podemos usar un cliente de MongoDB (o aplicación) para conectarnos y crear colecciones y documentos como si estuviéramos usando MongoDB, excepto que los datos se almacenan en una base de datos relacional poderosa, totalmente compatible con ACID, y escalable. ¡Probémoslo!
En la línea de comandos, usa la herramienta de shell de MongoDB para conectarte a la base de datos de MongoDB… espera… ¡en realidad es la base de datos MariaDB! Ejecuta lo siguiente:
mongosh
Por defecto, esta herramienta intenta conectarse a un servidor MongoDB (que, de nuevo, resulta ser MariaDB en este caso) que se ejecuta en tu máquina local (127.0.0.1) utilizando el puerto predeterminado (20017). Si todo sale bien, deberías poder ver la base de datos demo
listada cuando ejecutes el siguiente comando:
show databases
Cambia a la base de datos demo
:
use demo
Conectándose a MariaDB usando Mongo Shell.
Estamos conectados a una base de datos relacional desde un cliente no relacional. ¡Creemos la colección ratings
e insertemos algunos datos en ella:
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"
}
])
Verifica que las calificaciones se conserven en la base de datos:
db.ratings.find()
Consultando una base de datos MariaDB usando Mongo Shell.
Usando Funciones JSON en MariaDB
En este punto, tenemos una sola base de datos que, desde fuera, parece una base de datos NoSQL (MongoDB) y una base de datos relacional (MariaDB). Podemos conectarnos a la misma base de datos y escribir y leer datos desde clientes de MongoDB y clientes SQL. Todos los datos se almacenan en MariaDB, por lo que podemos usar SQL para unir datos de clientes de MongoDB o aplicaciones con datos de clientes de MariaDB o aplicaciones. Exploremos cómo MaxScale está usando MariaDB para almacenar datos de MongoDB (colecciones y documentos).
Conéctate a la base de datos usando un cliente SQL como mariadb-shell
y muestra las tablas en el esquema de demostración:
show tables in demo;
Deberías ver tanto las tablas books
como ratings
listadas. ratings
Fue creada como una colección de MongoDB. MaxScale tradujo los comandos enviados desde el cliente de MongoDB y creó una tabla para almacenar los datos en una tabla. Veamos la estructura de esta tabla:
describe demo.ratings;
A NoSQL collection is stored as a MariaDB relational table.
La tabla ratings
contiene dos columnas:
id
: el ID del objeto.doc
: el documento en formato JSON.
Si examinamos el contenido de la tabla, veremos que todos los datos sobre calificaciones se almacenan en la columna doc
en formato JSON:
SELECT doc FROM demo.ratings \G
Los documentos NoSQL se almacenan en una base de datos MariaDB.
Volvamos a nuestro objetivo original: mostrar los títulos de los libros con su información de calificación. Lo siguiente no es el caso, pero supongamos por un momento que la tabla ratings
es una tabla regular con columnas stars
y comment
. Si ese fuera el caso, unir esta tabla con la tabla books
sería fácil y nuestro trabajo estaría terminado:
/* this doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings r
JOIN books b USING(isbn)
Volvamos a la realidad. Necesitamos convertir la columna doc
de la tabla real ratings
en una expresión relacional que pueda usarse como una nueva tabla en la consulta. Algo como esto:
/* 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)
Ese algo es la función JSON_TABLE
. MariaDB incluye un conjunto completo de funciones JSON para manipular cadenas JSON. Utilizaremos la función JSON_TABLE
para convertir la columna doc
en una forma relacional que podamos usar para realizar uniones SQL. La sintaxis general de la función JSON_TABLE
es la siguiente:
JSON_TABLE(json_document, context_path COLUMNS (
column_definition_1,
column_definition_2,
...
)
) [AS] the_new_relational_table
Donde:
json_document
: una cadena o expresión que devuelve los documentos JSON a utilizar.context_path
: una expresión JSON Path que define los nodos a utilizar como fuente de las filas.
Y las definiciones de columnas (column_definition_1
, column_definition_2
, etc…) tienen la siguiente sintaxis:
new_column_name sql_type PATH path_in_the_json_doc [on_empty] [on_error]
Combinando este conocimiento, nuestra consulta SQL se vería de la siguiente manera:
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);
Unión de datos NoSQL y SQL en una sola consulta SQL.
Podríamos haber utilizado el valor ISBN como ObjectID de MongoDB y, en consecuencia, como la columna id
en la tabla ratings
, pero te lo dejo como ejercicio (pista: utiliza _id
en lugar de isbn
al insertar datos usando el cliente o la aplicación de MongoDB).
A Word on Scalability
Existe un error común de que las bases de datos relacionales no escalan horizontalmente (añadiendo más nodos) mientras que las bases de datos NoSQL sí. Pero las bases de datos relacionales escalan sin sacrificar las propiedades ACID. MariaDB tiene múltiples motores de almacenamiento adaptados a diferentes cargas de trabajo. Por ejemplo, puedes escalar una base de datos MariaDB implementando la fragmentación de datos con la ayuda de Spider. También puedes utilizar una variedad de motores de almacenamiento para manejar diferentes cargas de trabajo en una base por tabla. Las uniones entre motores son posibles en una sola consulta SQL.
Combinación de múltiples motores de almacenamiento en una sola base de datos lógica de MariaDB.
Otra alternativa más moderna es SQL distribuido con MariaDB Xpand. Una base de datos SQL distribuida se presenta como una única base de datos relacional lógica a las aplicaciones mediante el particionamiento transparente. Utiliza una arquitectura sin compartir que escala tanto la lectura como la escritura.
A distributed SQL database deployment.
Conclusión
¡Nuestro trabajo aquí está terminado! Ahora, sus sistemas pueden tener una vista escalable de 360 grados de sus datos que cumpla con ACID, independientemente de si fue creada por aplicaciones SQL o NoSQL. Hay menos necesidad de migrar sus aplicaciones de NoSQL a SQL o de hacer que las aplicaciones SQL sean políglotas de bases de datos. Si desea obtener más información sobre otras características en MaxScale, vea este video o visite la documentación.
Source:
https://dzone.com/articles/mixing-sql-and-nosql-with-mariadb-and-mongodb