lección 11
Tu entorno de práctica: DuckDB en local y en la nube
Instala DuckDB en tu portátil con pip, carga CSVs automáticamente, crea tu propia base de datos y entiende cuándo usar DuckDB vs PostgreSQL.
⏱ 50 min
Todo el SQL que has escrito hasta aquí se ha ejecutado en el navegador. Eso es perfecto para aprender y practicar, pero en tu trabajo real necesitarás un entorno local: explorar tus propios CSVs, conectar con bases de datos, automatizar con Python. En esta lección vas a instalar DuckDB en tu portátil — un pip install y listo — y vas a descubrir por qué es la herramienta favorita de los profesionales de datos para prototipar y explorar.
La analogía perfecta: la plataforma web es el simulador de vuelo (practicas sin riesgo). DuckDB en local es tu avioneta real (vuelas con datos de verdad, sin las restricciones del navegador). Y PostgreSQL — que verás más adelante con Docker — es el avión comercial de producción (múltiples pilotos, pasajeros, torre de control).
### Instalar DuckDB: un pip install y nada más
DuckDB se instala como cualquier librería de Python. Asegúrate de tener tu entorno virtual activado (lo creamos en la asignatura correspondiente) y ejecuta:
1source venv/bin/activate2pip install duckdb3python -c "import duckdb; print(f'DuckDB {duckdb.__version__} instalado correctamente')"
Instalación en Windows
Eso es todo. No hay servidor que levantar, no hay puerto que configurar, no hay usuario que crear. DuckDB vive dentro de tu proceso de Python. Cuando tu script termina, DuckDB se cierra limpiamente. Es la definición de "zero config".
Si no has creado un entorno virtual todavía, hazlo ahora: python -m venv venv y luego actívalo. Nunca instales librerías en el Python global del sistema — es una receta para el desastre.
### DuckDB en Python: conexión y queries
Hay dos modos de conexión: en memoria (los datos desaparecen al cerrar) y persistente (se guardan en un archivo .duckdb). Para explorar y prototipar, usa memoria. Para proyectos reales, usa un archivo:
1import duckdb23# Modo 1: En memoria (datos temporales)4con = duckdb.connect()5result = con.sql("SELECT 42 AS respuesta, CURRENT_DATE AS hoy")6print(result)78# Modo 2: Persistente (se guarda en disco)9con = duckdb.connect('mi_proyecto.duckdb')10con.sql("CREATE TABLE IF NOT EXISTS test (id INTEGER, nombre VARCHAR)")11con.sql("INSERT INTO test VALUES (1, 'Hola DuckDB')")12print(con.sql("SELECT * FROM test"))
Dos modos: en memoria (exploración) y persistente (proyectos)
### generate_series: crear datos de prueba al vuelo
Una de las funciones más útiles de DuckDB es generate_series. Genera secuencias de números que puedes usar para crear tablas de prueba sin necesitar un CSV. Es como un generador de datos bajo demanda:
1import duckdb23con = duckdb.connect()45# Generar 10 clientes ficticios6result = con.sql("""7 SELECT8 i AS id,9 'Cliente_' || i AS nombre,10 ['Madrid','Barcelona','Valencia','Sevilla','Bilbao'][1 + (i % 5)] AS ciudad,11 (random() * 1000)::INTEGER AS gasto_total12 FROM generate_series(1, 10) AS t(i)13""")14print(result)
generate_series + expresiones = datos de prueba instantáneos
### Cargar CSVs: donde DuckDB es mágico
En PostgreSQL, cargar un CSV requiere CREATE TABLE con tipos explícitos, COPY FROM, gestionar errores de encoding... En DuckDB, una línea. La función read_csv_auto detecta separadores, tipos de datos, cabeceras y encoding automáticamente:
1import duckdb23con = duckdb.connect()45# Cargar un CSV en una tabla (DuckDB infiere TODO)6con.sql("""7 CREATE TABLE ventas AS8 SELECT * FROM read_csv_auto('datos/ventas_2024.csv')9""")1011# ¿Qué tipos detectó?12con.sql("DESCRIBE ventas").show()1314# Primera query analítica15con.sql("""16 SELECT17 region,18 COUNT(*) AS num_ventas,19 SUM(importe)::INTEGER AS total,20 ROUND(AVG(importe), 2) AS ticket_medio21 FROM ventas22 GROUP BY region23 ORDER BY total DESC24""").show()
read_csv_auto: carga CSVs sin definir esquema — DuckDB lo infiere solo
DuckDB también puede leer Parquet (read_parquet), JSON (read_json) y archivos remotos por HTTP. Incluso puedes hacer SELECT * FROM read_csv_auto("https://...url.../datos.csv"). Esto lo exploraremos a fondo en la asignatura correspondiente (Data Lakes).
### Crear tu propia base de datos: ecommerce.duckdb
Vamos a crear una base de datos persistente con datos de un e-commerce. La usarás para practicar fuera de la plataforma web:
1import duckdb23con = duckdb.connect('ecommerce.duckdb')45# Categorías6con.sql("""7 CREATE OR REPLACE TABLE categorias AS8 SELECT * FROM (VALUES9 (1, 'Electrónica', 'Dispositivos y gadgets'),10 (2, 'Hogar', 'Muebles y decoración'),11 (3, 'Ropa', 'Moda y accesorios'),12 (4, 'Deportes', 'Equipamiento deportivo'),13 (5, 'Libros', 'Libros y material educativo')14 ) AS t(id, nombre, descripcion)15""")1617# Productos (200 productos con categoria_id)18con.sql("""19 CREATE OR REPLACE TABLE productos AS20 SELECT21 i AS id,22 'Producto_' || i AS nombre,23 ['Electrónica','Hogar','Ropa','Deportes','Libros'][1 + (i % 5)] AS categoria,24 1 + (i % 5) AS categoria_id,25 ROUND(5 + (i * 37) % 200 + ((i * 13) % 100) / 100.0, 2) AS precio,26 10 + (i * 73) % 490 AS stock27 FROM generate_series(1, 200) AS t(i)28""")2930# Clientes (1000)31con.sql("""32 CREATE OR REPLACE TABLE clientes AS33 SELECT34 i AS id,35 'Cliente_' || i AS nombre,36 'cliente' || i || '@email.com' AS email,37 ['Madrid','Barcelona','Valencia','Sevilla','Bilbao'][1 + (i % 5)] AS ciudad,38 DATE '2020-01-01' + INTERVAL (i * 3) DAY AS fecha_registro,39 ['email','google','facebook','organico','referido'][1 + (i % 5)] AS canal_adquisicion,40 (i % 7 = 0) AS es_vip41 FROM generate_series(1, 1000) AS t(i)42""")4344# Pedidos (5000 con producto_id)45con.sql("""46 CREATE OR REPLACE TABLE pedidos AS47 SELECT48 i AS id,49 1 + (i % 1000) AS cliente_id,50 1 + (i % 200) AS producto_id,51 1 + (i % 5) AS cantidad,52 DATE '2023-01-01' + INTERVAL (i % 730) DAY AS fecha,53 ROUND(10 + (i * 37) % 491 + ((i * 13) % 100) / 100.0, 2) AS importe,54 CASE WHEN i % 10 < 7 THEN 'completado'55 WHEN i % 10 < 9 THEN 'cancelado'56 ELSE 'devuelto' END AS estado57 FROM generate_series(1, 5000) AS t(i)58""")5960# Líneas de pedido (detalle de cada pedido)61con.sql("""62 CREATE OR REPLACE TABLE lineas_pedido AS63 SELECT64 i AS id,65 1 + (i % 5000) AS pedido_id,66 1 + (i % 200) AS producto_id,67 1 + (i % 4) AS cantidad,68 ROUND(5 + (i * 41) % 200 + ((i * 17) % 100) / 100.0, 2) AS precio_unitario69 FROM generate_series(1, 10000) AS t(i)70""")7172print('Base de datos creada: ecommerce.duckdb')73for tabla in ['categorias', 'productos', 'clientes', 'pedidos', 'lineas_pedido']:74 n = con.sql(f'SELECT COUNT(*) FROM {tabla}').fetchone()[0]75 print(f" {tabla}: {n} filas")
Script completo: crea todas las tablas que usarás en las lecciones L3-L11
### DuckDB vs PostgreSQL: no son rivales, son compañeros
Un error común es pensar que DuckDB reemplaza a PostgreSQL. No. Son herramientas complementarias con propósitos distintos. PostgreSQL es tu base de datos de producción: gestiona transacciones, usuarios concurrentes, integridad referencial. Es donde tu aplicación web guarda los pedidos en tiempo real. DuckDB es tu laboratorio personal: exploras datos, pruebas queries, generas reportes, analizas CSVs.
La analogía: PostgreSQL es la cocina del restaurante (producción, volumen, múltiples cocineros, pedidos en tiempo real, normas de seguridad alimentaria). DuckDB es tu cocina en casa (experimentas, pruebas recetas nuevas, analizas ingredientes, sin presión de servicio). Ambas son cocinas, pero con propósitos completamente diferentes.
- PostgreSQL: miles de usuarios simultáneos, inserciones en tiempo real, ACID completo, permisos por usuario. Necesita servidor (Docker).
- DuckDB: un solo usuario (tú), lecturas masivas, sin servidor, cabe en un pip install. Ideal para analítica y exploración.
- En tu carrera usarás AMBOS: PostgreSQL para los datos de producción, DuckDB para analizarlos sin tocar producción.
- La sintaxis SQL es 95% idéntica. Lo que aprendes en uno funciona en el otro.
No uses DuckDB como base de datos de una aplicación web. No está diseñado para múltiples escritores concurrentes. Para eso existe PostgreSQL (que verás en la asignatura correspondiente de Docker). DuckDB es tu herramienta de análisis, no tu base de producción.
### Verificación final: un JOIN en tu base local
1import duckdb23con = duckdb.connect('ecommerce.duckdb')45# Si ves resultados, tu entorno local funciona perfectamente6con.sql("""7 SELECT8 c.ciudad,9 COUNT(DISTINCT c.id) AS clientes,10 COUNT(p.id) AS pedidos,11 SUM(p.importe)::INTEGER AS gasto_total,12 ROUND(AVG(p.importe), 2) AS ticket_medio13 FROM clientes c14 LEFT JOIN pedidos p ON p.cliente_id = c.id15 WHERE p.estado = 'completado'16 GROUP BY c.ciudad17 ORDER BY gasto_total DESC18""").show()
Si ves una tabla con 5 ciudades y sus métricas, todo funciona correctamente.
Ya tienes dos entornos de práctica: la plataforma web (inmediata, sin instalar nada) y DuckDB en tu portátil (para tus propios datos, automatización con Python y trabajo profesional). A partir de la próxima lección, todos los ejercicios SQL se ejecutan directamente aquí en el navegador. Si quieres practicar más, replica los ejercicios en tu DuckDB local.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...