DuckDB alcanzó la versión 1.0 en junio de 2024 y acaba de publicar la 1.1 en septiembre. Después de años siendo “esa cosa curiosa que usan los investigadores”, el proyecto ha llegado a un punto de madurez en el que empieza a desplazar herramientas con las que nadie pensaba competir: pandas, Spark en local e incluso, para muchos casos, el data warehouse en la nube. Este artículo es un intento de explicar, sin exageraciones, dónde encaja realmente y dónde no.
Qué es y por qué importa
La descripción corta es fácil: DuckDB es a la analítica lo que SQLite es a las bases transaccionales. Una biblioteca embebida, sin servidor, sin daemon, sin credenciales, que se carga dentro del proceso de tu aplicación o notebook y expone un motor SQL completo. La descripción larga es más interesante, porque lo que lo hace diferente no es la forma sino el diseño interno.
DuckDB es columnar y vectorizado. En lugar de procesar fila a fila, agrupa los valores en vectores de unos pocos miles de elementos y aplica cada operación sobre el vector entero. Eso permite aprovechar las instrucciones SIMD de la CPU, mantener los datos calientes en la caché L1/L2 y, en la práctica, acercarse mucho al límite teórico del hardware. Para cargas analíticas —agregaciones, joins, ventanas, escaneos masivos— esa decisión arquitectónica es la diferencia entre segundos y minutos.
La diferencia entre OLAP y OLTP, otra vez
Conviene recordar por qué no todas las bases de datos sirven para lo mismo. Un sistema OLTP como PostgreSQL o MySQL está pensado para transacciones cortas, concurrentes, que tocan pocas filas cada una: insertar un pedido, actualizar un saldo, leer un perfil de usuario. La fila es la unidad natural porque normalmente la quieres entera. Los índices B-tree, el log de transacciones y el MVCC están optimizados para esa carga.
Un motor analítico vive en el extremo opuesto. Las consultas leen millones de filas pero solo tres o cuatro columnas, los joins son grandes, las agregaciones barren el dataset completo y la concurrencia de escritura es baja o inexistente. Almacenar los datos por columnas permite leer únicamente lo que la consulta pide, comprimir mucho mejor —los valores de una columna se parecen entre sí— y aplicar operaciones vectorizadas. Por eso DuckDB gana frente a Postgres en estos escenarios: no porque Postgres sea lento, sino porque está optimizado para otra cosa.
La tabla clásica ilustra la magnitud:
| Tarea | pandas | DuckDB | Spark local |
|---|---|---|---|
| Consulta sobre 1 GB de CSV | 30 s | 2 s | 10 s |
| Agregación sobre 10 GB de Parquet | OOM | 5 s | 20 s |
| Join de dos tablas de 100 M filas | OOM | 15 s | 40 s |
En un portátil decente, DuckDB resuelve en segundos lo que pandas ni siquiera puede cargar y lo que Spark tarda decenas de segundos en coordinar entre sus ejecutores.
Qué significa “analítica local”
La expresión local analytics suena modesta, pero describe un cambio de postura importante. Durante años, la respuesta por defecto a “tengo datos que analizar” era subirlos a un warehouse —Snowflake, BigQuery, Redshift— aunque fueran diez gigas. Se pagaba almacenamiento, se pagaba compute por consulta, se pagaba egress cuando había que sacarlos, y se pagaba la complejidad de mover datos que cabían perfectamente en la memoria de una máquina moderna.
DuckDB invierte esa lógica. Un laptop con 32 GB de RAM y un SSD NVMe es capaz de ejecutar consultas sobre cientos de gigabytes de Parquet, streameando desde disco, sin llenarse de memoria, sin clúster, sin factura. El lee-archivos-directamente es la parte que más sorprende la primera vez: apuntas a un .parquet, a un glob de varios, a una ruta s3:// o incluso a una URL https:// y el motor resuelve el acceso, la inferencia de esquema, los push-downs de predicado y la proyección de columnas por ti. Los datos no se mueven a una tabla interna; se leen donde están. Esto cambia completamente el flujo de trabajo: exploración, prototipado, ETL, validaciones de CI, pre-procesado para ML y generación de datasets derivados dejan de ser proyectos de infraestructura para convertirse en un script corto.
Cómo encaja en un proyecto real
El ejemplo canónico es reemplazar pandas en la fase de exploración y preparación de datos. La API es deliberadamente amistosa con el ecosistema: puedes ejecutar SQL sobre un DataFrame de pandas, sobre uno de Polars, sobre un RecordBatch de Arrow o sobre archivos en disco, y devolver el resultado de nuevo en cualquiera de esos formatos, casi siempre sin copiar memoria.
import duckdb
# Abrir una conexión in-memory y consultar Parquet remoto directamente
con = duckdb.connect()
con.execute("INSTALL httpfs; LOAD httpfs;")
df = con.execute("""
SELECT category, SUM(amount) AS total, COUNT(*) AS n
FROM 's3://bucket/ventas/*.parquet'
WHERE date >= '2024-01-01'
GROUP BY category
ORDER BY total DESC
""").df()
Ese único bloque cubre tres ideas que antes requerían herramientas separadas: lectura streaming de un data lake, agregación analítica sobre varios archivos y entrega del resultado como DataFrame listo para graficar. Las extensiones (httpfs, spatial, json, sqlite, postgres, icu) se instalan con una línea y amplían el motor sin tocar la instalación base.
En equipos más formales, DuckDB se ha convertido en el adaptador por defecto de dbt para desarrollo local: compilas, testeas y materializas modelos contra un fichero .duckdb en tu máquina antes de promocionar a producción. Y si el volumen crece, MotherDuck ofrece el mismo motor en cloud con sintaxis idéntica, cosa que permite escalar sin reescribir.
Dónde DuckDB no es la respuesta
La honestidad pide recordar los límites. DuckDB no es multi-usuario con escrituras concurrentes: un escritor a la vez y muchos lectores. No es un motor transaccional para aplicaciones de usuario final; para eso siguen estando Postgres o SQLite. No es streaming en tiempo real al estilo de Flink o ksqlDB. Y cuando el dataset productivo supera los cientos de gigabytes y lo consultan varios equipos con SLA, un warehouse gestionado sigue siendo la opción correcta: pagas por no operar tú la infraestructura.
Conclusión
Lo que hace interesante a DuckDB en este momento de madurez no es que sea rápido —hay motores rápidos desde hace décadas— sino que ha eliminado la fricción entre tener un problema analítico y resolverlo. No hay clúster que levantar, ni warehouse que aprovisionar, ni datos que mover, ni factura que vigilar. Se instala con pip, lee los archivos donde ya están y devuelve resultados en segundos. Para la enorme mayoría de cargas de trabajo por debajo del centenar de gigabytes —que es donde vive la mayoría del análisis real en empresas pequeñas y medianas— esa combinación hace que las alternativas parezcan, de pronto, desproporcionadas. No sustituye al warehouse; redefine dónde empieza a hacer falta uno.