Saltar a contenido

06 · MySQL y MariaDB

Cuaderno asociado

cuadernos/05_mysql_mariadb.ipynb. Volver al 00 - Índice de la demo.

DuckDB lleva años leyendo datos desde MariaDB/MySQL. Lo nuevo de la 2.0 es poder ejecutar consultas remotamente: CONNECT redirige la sesión y el optimizador de pushdown manda el SQL al servidor remoto en lugar de traerse la tabla entera.

sequenceDiagram
    autonumber
    participant PY as Python / DuckDB
    participant PUSH as Optimizador pushdown
    participant DB as MariaDB
    PY->>PUSH: CONNECT 'mysql:host=... database=eurostar'
    PY->>PUSH: SELECT pais, count(*) FROM estaciones GROUP BY 1
    PUSH->>DB: SELECT pais, count(*) FROM estaciones GROUP BY 1
    DB-->>PUSH: 12 filas agregadas
    PUSH-->>PY: 12 filas
    Note over PUSH,DB: Se transfiere el RESULTADO,<br/>no la tabla completa

Dos formas de llegar al mismo sitio

A) ATTACH + catalogo (lo clásico, 1.x-2.0)

INSTALL mysql;
LOAD mysql;

ATTACH 'host=localhost user=demo password=*** database=eurostar'
    AS mysql_db (TYPE mysql, READ_ONLY);

USE mysql_db;
SELECT * FROM estaciones LIMIT 5;

Las tablas se comportan como locales, pero cada SELECT va a MySQL en el momento de la consulta.

B) CONNECT con cadena de conexión (lo nuevo de 2.0)

CONNECT 'mysql:host=localhost user=demo password=*** database=eurostar';

SELECT pais, count(*) AS n FROM estaciones GROUP BY 1 ORDER BY n DESC;

DISCONNECT;

La cadena no es un DSN mysql://

El formato es mysql: seguido de pares clave=valor estilo libpq.

Esto es incorrecto: CONNECT 'mysql://user:pass@host/db'.

Y esto es correcto: CONNECT 'mysql:host=localhost user=demo password=*** database=eurostar'.

El error típico es IOException: Failed to connect to MySQL database with parameters ....

Delegar el trabajo al servidor

-- Agregación: se ejecuta en MariaDB
SELECT categoria, sum(importe) AS total
FROM mysql_db.ventas
GROUP BY categoria;

-- SQL arbitrario, lectura
SELECT * FROM mysql_query('mysql_db', 'SELECT * FROM estaciones LIMIT 3');

-- SQL arbitrario, escritura / DDL
CALL mysql_execute('mysql_db', 'CREATE TABLE tmp_demo (i INTEGER)');

El patrón estrella: MySQL → Parquet

COPY (SELECT * FROM mysql_db.ventas WHERE fecha >= '2025-01-01')
TO 'datos/ventas_2025.parquet' (FORMAT PARQUET, COMPRESSION zstd);

Descargas una vez desde el OLTP y analizas mil veces sobre Parquet. Es el caso de uso que más dinero ahorra en equipos pequeños: no es procedente montar un Data Warehouse para eso.

El sentido contrario: Parquet → MySQL

COPY mysql_db.resumen FROM 'datos/resumen.parquet';

Cuándo CONNECT y cuándo ATTACH

Necesitas… Usa Motivo
Un JOIN entre MySQL y Parquet local ATTACH Necesitas ambas tablas en el mismo plan
Que el GROUP BY lo haga el servidor CONNECT Todo el SQL viaja al motor remoto
Solo una foto para analizar COPY ... TO parquet Cero dependencia del servidor después
Escribir en MySQL desde SQL ATTACH (+INSERT/COPY) El catálogo remoto es escribible

⚠️ Nota sobre el cuaderno 05_mysql_mariadb.ipynb

El cuaderno está escrito para conectarse a un MariaDB real. Si no hay servidor escuchando entra en modo simulación: crea una tabla local equivalente y muestra el mismo SQL, avisando por pantalla. Así el taller nunca se atasca por infraestructura, pero las celdas conectadas solo demuestran pushdown de verdad cuando hay servidor.

Script mínimo para tener el servidor listo:

docker run -d --name mariadb-demo -p 3306:3306 \
  -e MARIADB_ROOT_PASSWORD=root -e MARIADB_DATABASE=eurostar mariadb:11

Ejercicios

  1. Escribe las dos variantes (A y B) para conectarte a una base eurostar y listar las tablas de information_schema.
  2. Ejecuta la misma agregación con ATTACH y con CONNECT, y compara los planes.
  3. Exporta la tabla estaciones a Parquet comprimido y mide cuánto ocupa frente a la tabla original.
  4. Explica por qué CONNECT puede ser más rápido que ATTACH para un GROUP BY sobre 50 M de filas.

Soluciones en cuadernos/99_soluciones.ipynb.