Ir al contenido principal

DuckDB frente a SQLite: Una comparación completa de bases de datos

Aprende las principales diferencias entre DuckDB y SQLite y cómo se comparan entre sí.
Actualizado 7 nov 2025  · 15 min de lectura

En la gestión moderna de datos, las bases de datos integradas ligeras desempeñan un papel crucial en el funcionamiento de aplicaciones, flujos de trabajo y análisis. Dos sistemas que a menudo se comparan sonDuckDB ( ) y SQLite

Ambas son bases de datos integradas, pero tienen fines diferentes: SQLite destaca en cargas de trabajo transaccionales, mientras que DuckDB está optimizado para consultas analíticas.

En este artículo comparativo, analizaremos las diferencias entre ambas bases de datos.

De un vistazo: DuckDB frente a SQLite

Aquí tienes una tabla comparativa que muestra las similitudes y diferencias entre DuckDB y SQLite. Para obtener más información, consulta la explicación que se incluye a lo largo de este artículo. 

Categoría SQLite DuckDB
Año de lanzamiento 2000 2019
Objetivo principal Base de datos transaccional (OLTP) ligera Base de datos analítica integrada (OLAP)
Modelo de almacenamiento Basado en filas Columnar
Tipo de carga de trabajo OLTP (inserción, actualización, eliminación, búsquedas puntuales) OLAP (agregaciones, uniones, exploraciones)
Ejecución de consultas Basado en iterador (fila por fila) Vectorizado (por lotes)
Rendimiento Fuerza Excelente para transacciones pequeñas y frecuentes. Excelente para consultas analíticas en grandes conjuntos de datos.
Modelo de concurrencia Un solo escritor, múltiples lectores Ejecución paralela de consultas en todos los núcleos de la CPU
Gestión del tamaño de los datos Optimizado para conjuntos de datos pequeños y medianos. Maneja conjuntos de datos más grandes que la memoria (ejecución fuera del núcleo).
Formatos de archivo compatibles Solo archivo SQLite propietario Compatibilidad nativa con Parquet, Arrow y CSV.
Acceso a datos externos Requiere importación antes de realizar la consulta. Consultar archivos directamente sin importarlos
Integraciones Amplia compatibilidad con lenguajes (C, Python, Java, PHP, etc.) Integración profunda de la ciencia de datos (Python, R, pandas, Jupyter)
Integración en la nube Funciones locales prioritarias y funciones limitadas en la nube Integración nativa con S3, Azure y GCS para Parquet/Arrow.
Transacciones y ACID Totalmente compatible con ACID ACID dentro de un único proceso, menos robusto para escrituras simultáneas.
Configuración y dependencias Sin configuración, biblioteca C única Instalación sencilla, pero con dependencias opcionales (Arrow, Pandas).
Características de SQL Centrado en CRUD; compatibilidad parcial con SQL analítico. Sólida compatibilidad con ANSI SQL con análisis avanzados (CTE, funciones de ventana)
Casos de uso típicos Aplicaciones móviles, dispositivos IoT, cachés locales Ciencia de datos, paneles de BI, canalizaciones ETL
Escalabilidad Limitado a la ejecución de un solo subproceso. Paralelismo multinúcleo y desbordamiento de disco para grandes cargas de trabajo
Mantenimiento Mínimo; VACUUM ocasional para liberar espacio. Mínimo; gestión de parquet particionado para mayor eficiencia.
Ideal para Aplicaciones integradas que necesitan un almacenamiento local fiable Flujos de trabajo analíticos en Python/R o contextos sin servidor.
Ejemplo de contexto de consulta SELECT * FROM usuarios WHERE id=1; SELECT región, AVG(importe) FROM ventas GROUP BY región;

¿Qué es SQLite?

SQLite es una de las bases de datos más utilizadas en todo el mundo. Lanzado en 2000, SQLite fue diseñado como un gestor de bases de datos ligero y sin servidor motor de base de datos SQL.

Estas son algunas de sus características principales:

  • Autónomo y sin servidor
  • Configuración sin necesidad de ajustes
  • Totalmente conforme con ACID
  • Almacenamiento orientado a filas

Debido a su arquitectura ligera, se puede utilizar en los siguientes casos de uso:

  • Aplicaciones móviles (Android, iOS)
  • Software de escritorio
  • Sistemas integrados como dispositivos IoT

La principal ventaja de SQLite reside en su simplicidad y fiabilidad. Los programadores pueden enviar una única base de datos basada en archivos con su aplicación sin preocuparse por las dependencias externas.

¿Qué es DuckDB?

DuckDB A menudo se hace referencia a DuckDB como el SQLite para análisis. Introducido en 2019, DuckDB fue desarrollado en el CWI. El objetivo principal de utilizar DuckDB era disponer de una solución de base de datos OLAP en proceso solución de base de datos OLAP en proceso.

Estas son algunas de sus características principales:

  • Formato de almacenamiento en columnas
  • Optimizado para cargas de trabajo OLAP
  • Ejecución de consultas vectorizadas
  • Diseño integrado en proceso
  • Compatibilidad directa con formatos de archivo como Parquet y Arrow

Algunos casos de uso típicos incluyen:

  • Análisis interactivo
  • Flujos de trabajo de ciencia de datos (Python, R, Jupyter)
  • Canales ETL ligeros

La ventaja principal de utilizar DuckDB es que ofrece la potencia de las bases de datos analíticas (como Snowflake o BigQuery) en un paquete integrado.

DuckDB frente a SQLite: Diferencias y similitudes clave

1. Instalación y dependencias

SQLite

SQLite es famoso por no tener dependencias. Se compila en una única biblioteca C que se puede integrar en prácticamente cualquier aplicación.

La instalación es mínima y se puede descargar fácilmente desde el sitio web de SQLite.

La portabilidad es una de sus mayores ventajas: funciona igual en Windows, macOS, Linux, iOS y Android sin apenas esfuerzo adicional.

DuckDB

DuckDB también es fácil de instalar, pero se distribuye como binarios independientes o paquetes Python/R en lugar de venir preinstalado de forma universal.

Tiene algunas dependencias más, especialmente cuando se habilitan integraciones con Apache Arrow, Parquet o Pandas.

La huella aún es pequeña, pero en comparación con SQLite, DuckDB requiere una configuración ligeramente mayor si deseas funciones avanzadas como conectores de almacenamiento en la nube o integración de herramientas de ciencia de datos.

2. Formatos y arquitectura de almacenamiento

SQLite 

Almacena datos en un formato basado en filas, optimizado para OLTP (procesamiento de transacciones en línea) , como inserciones, actualizaciones y eliminaciones.

Recuperar una fila completa es rápido, pero las consultas analíticas que solo escanean unas pocas columnas entre millones de filas pueden ralentizarse debido a la lectura de datos innecesarios.

DuckDB

DuckDB utiliza un motor de almacenamiento columnar, diseñado específicamente para OLAP (procesamiento analítico en línea).

El formato columnar significa que las consultas que agregan grandes conjuntos de datos (por ejemplo, AVG(sales) o COUNT(*)) son mucho más rápidas, ya que solo se leen en la memoria las columnas relevantes.

También permite una mejor compresión y ejecución vectorizada para aumentar la velocidad.

Ejemplo: Una consulta « SELECT * FROM sales WHERE customer_id=123 » se ejecuta más rápido en SQLite, mientras que « SELECT AVG(amount) FROM sales GROUP BY region » se ejecuta mucho más rápido en DuckDB.

3. Cargas de trabajo transaccionales frente a analíticas

Las dos bases de datos también difieren en vuestras cargas de trabajo:

  • OLTP (transaccional): Operaciones breves y frecuentes (por ejemplo, aplicaciones bancarias, perfiles de usuario, sistemas de punto de venta). Sus prioridades son la baja latencia, la integridad de los datos y el acceso simultáneo.
  • OLAP (analítico): Consultas complejas sobre grandes conjuntos de datos (por ejemplo, paneles de control, herramientas de BI, análisis de datos ad hoc). Sus prioridades son el rendimiento, la capacidad de exploración y la velocidad de agregación.

SQLite

SQLite está optimizado para OLTP (inserción, actualización, eliminación y búsquedas puntuales).

Por ejemplo:

  • Aplicaciones móviles que almacenan datos sin conexión.
  • Dispositivos IoT que registran las interacciones de los usuarios.
  • Cachés locales en aplicaciones de escritorio.

DuckDB

DuckDB está optimizado para OLAP (agregaciones, uniones, exploraciones).

Por ejemplo:

  • Científicos de datos que realizan agregaciones en archivos Parquet/CSV.
  • Interactivo Paneles de BI donde las consultas resumen millones de filas.
  • Canales ETL/ELT que requieren transformaciones ligeras en memoria.

4. Soporte y sintaxis SQL

A continuación, veamos su sintaxis SQL. Ambos implementan un amplio subconjunto del estándar SQL con extensiones; ninguno de los dos es totalmente compatible con ANSI.

SQLite

  • Admite una gran parte del estándar SQL, pero omite las construcciones analíticas avanzadas.
  • Ideal para operaciones CRUD y uniones más sencillas.
  • Admite funciones de ventana y CTE, pero carece de funciones analíticas más avanzadas, como GROUPING SETS y algunas extensiones agregadas.

Así es como se ve la sintaxis:

CREATE TABLE sales (
    id INTEGER PRIMARY KEY,
    product TEXT,
    amount REAL,
    sale_date TEXT
);

DuckDB

  • Mucho más cercano al cumplimiento de ANSI SQL, con un sólido soporte para funciones de ventana, CTE, agregaciones y operaciones de conjunto.
  • Diseñado para parecer un PostgreSQL ligero para análisis.
  • La integración con Arrow y Pandas permite ejecutar SQL directamente en conjuntos de datos externos sin necesidad de importarlos primero.

Aquí hay un ejemplo similar de cómo es la sintaxis para DuckDB:

CREATE TABLE sales (
    id INTEGER,
    product VARCHAR,
    amount DOUBLE,
    sale_date DATE
);

SQLite frente a DuckDB: Arquitectura fundamental y filosofía de diseño

En términos de arquitectura fundamental, SQLite y DuckDB son bases de datos integradas en proceso. Sin embargo, sus filosofías de diseño son diferentes. 

SQLite da prioridad a la simplicidad y fiabilidad transaccional, mientras que DuckDB está optimizado para cargas de trabajo analíticas y la integración moderna de la ciencia de datos.

1. Arquitectura de almacenamiento

En primer lugar, las dos bases de datos difieren en su arquitectura de almacenamiento.

SQLite

SQLite se basa en filas, lo que resulta ideal para el acceso transaccional. Esto significa que las filas completas se almacenan juntas en el disco.

Este diseño beneficia a las cargas de trabajo transaccionales (OLTP), ya que insertar, actualizar o recuperar un solo registro normalmente solo requiere acceder a una fila.

Las aplicaciones que necesitan un acceso rápido y constante a registros individuales, como perfiles de usuario o detalles de pedidos, funcionarán de manera eficiente en este modelo.

DuckDB

DuckDB adopta un formato columnar, diseñado para escanear rápidamente miles de millones de filas. Tener un formato columnar significa agrupar los valores de la misma columna en el disco y en la memoria.

El almacenamiento en columnas permite realizar consultas analíticas (OLAP) muy eficientes, ya que las agregaciones, los filtros y los escaneos suelen requerir el acceso solo a un subconjunto de columnas.

Las técnicas de compresión se aplican de forma más eficaz en todas las columnas, lo que reduce el uso de memoria y almacenamiento al tiempo que mejora el rendimiento del escaneo.

2. Metodologías de procesamiento de consultas

A continuación, tendremos que ver cómo procesa cada uno de ellos las consultas.

En general, el modelo de SQLite está optimizado para ofrecer simplicidad y corrección transaccional, mientras que el motor vectorizado de DuckDB está diseñado para ofrecer rendimiento y capacidad analítica.

SQLite

SQLite utiliza un modelo tradicional basado en iteradores, que procesa una fila cada vez a través del canal de consultas.

Este enfoque de ejecución fila por fila es ligero y se adapta a las cargas de trabajo transaccionales, en las que las consultas suelen implicar pequeños conjuntos de datos e inserciones o actualizaciones frecuentes.

Sin embargo, aparecen cuellos de botella en el rendimiento cuando las consultas deben escanear grandes conjuntos de datos, ya que la evaluación fila por fila añade una sobrecarga.

DuckDB

DuckDB emplea la ejecución de consultas vectorizadas, procesando lotes de filas (vectores) a la vez en lugar de una por una.

Este enfoque minimiza la sobrecarga de la CPU, aprovecha mejor las cachés de las CPU modernas y permite el paralelismo SIMD (instrucción única, datos múltiples).

La ejecución vectorizada resulta especialmente ventajosa para el análisis: operaciones como agregaciones, uniones y filtros se ejecutan mucho más rápido en grandes volúmenes de datos.

En DuckDB, la siguiente consulta se beneficia del almacenamiento en columnas y el procesamiento vectorizado, lo que la hace significativamente más rápida.

SELECT region, AVG(amount)
FROM sales
GROUP BY region;

3. Arquitectura de base de datos en proceso

Por último, SQLite y DuckDB son bases de datos integradas, lo que significa que se ejecutan dentro del proceso de la aplicación host en lugar de como un servidor de base de datos independiente.

Esta arquitectura elimina la latencia de la red, simplifica la implementación y reduce la carga operativa que supone la gestión de servicios externos.

Esto los convierte en:

  • Fácil de distribuir
  • Fácil de implementar
  • Baja latencia (sin sobrecarga cliente-servidor)

SQLite 

SQLite fue pionero en la idea de ser una base de datos «sin servidor». Esto significa que tus aplicaciones se vinculan directamente a su biblioteca y todas las consultas se ejecutan dentro de la propia aplicación.

DuckDB 

DuckDB sigue un diseño similar en proceso, pero lo aplica a contextos analíticos.

Para evitar la sobrecarga que supone poner en marcha motores analíticos externos, DuckDB aprovecha los entornos de ciencia de datos (Python, R o incluso cuadernos Jupyter) ejecutando consultas en ellos.

Análisis de rendimiento y comparativa entre DuckDB y SQLite

El rendimiento es uno de los diferenciadores más importantes entre DuckDB y SQLite. Aunque ambas son bases de datos integradas, sus prioridades de diseño influyen en su comportamiento ante diferentes cargas de trabajo. 

En general, SQLite tiene un gran rendimiento en casos de uso transaccional, mientras que DuckDB funciona bien en contextos analíticos.

1. Rendimiento de las consultas analíticas

DuckDB:

  • Supera a SQLite en agregaciones, uniones y agrupaciones.
  • Puede consultar archivos Parquet/Arrow directamente.
  • DuckDB está diseñado para la ejecución de consultas analíticas y suele superar a SQLite en el procesamiento de grandes conjuntos de datos.

Veamos cómo se puede comprobar esto mediante una consulta de agregación.

Supongamos que tenemos un conjunto de datos de ventas (sales.csv) con 10 millones de filas que contienen order_id, customer_id, amount y date.

SQLite (Python):

Para ejecutar esta consulta en SQLite utilizando Python, tendremos que cargar el CSV en un DataFrame y leerlo en una base de datos de conexión SQLite3, y ejecutar nuestra consulta SQL dentro de ella.

Aquí tienes un ejemplo de código:

import sqlite3
import pandas as pd

# Load CSV into SQLite
df = pd.read_csv("sales.csv")
conn = sqlite3.connect("sales.db")
df.to_sql("sales", conn, if_exists="replace", index=False)

# Run a GROUP BY query directly on the imported table
cursor = conn.execute("""
    SELECT customer_id, SUM(amount) AS total_spent
    FROM sales
    GROUP BY customer_id
    ORDER BY total_spent DESC
    LIMIT 5
""")
print(cursor.fetchall())

DuckDB (Python):

Para ejecutar una consulta similar utilizando DuckDB en Python, hay menos pasos que seguir. No se necesita un marco de datos.

Aquí tienes un ejemplo de código:

import duckdb

con = duckdb.connect()
# Run a GROUP BY query directly on the CSV file
result = con.execute(""" SELECT customer_id, SUM(amount) AS total_spent FROM read_csv_auto('sales.csv') GROUP BY customer_id ORDER BY total_spent DESC LIMIT 5 """).fetchdf()
print(result)

2. Rendimiento de la carga de trabajo transaccional

En términos de carga de trabajo transaccional, cada base de datos tiene sus propios casos de uso únicos.

SQLite está optimizado para cargas de trabajo con muchas transacciones y consultas puntuales. Maneja operaciones frecuentes de INSERT, UPDATE y DELETE con una sobrecarga muy baja, lo que lo hace ideal para sistemas transaccionales integrados.

SQLite admite inserciones masivas de forma eficiente mediante transacciones y funciona bien cuando se requieren pequeñas actualizaciones con frecuencia.

DuckDB, por el contrario, se centra en las consultas analíticas tras la ingesta de datos, en lugar de en las actualizaciones transaccionales de alta frecuencia.

3. Escalabilidad y utilización de recursos

SQLite

SQLite es ligero y se utiliza a menudo para conjuntos de datos pequeños y medianos. Una sola consulta se ejecuta en un subproceso y SQLite utiliza un modelo de escritor único con lecturas simultáneas; no paraleliza una sola consulta SELECT, lo que puede limitar el rendimiento analítico.

DuckDB

DuckDB admite paralelismo multinúcleo y consultas que superan la capacidad de la memoria. Se adapta aprovechando la ejecución paralela y puede extenderse al disco cuando es necesario, lo que permite realizar análisis fuera del núcleo.

Esto te permite analizar conjuntos de datos que superan con creces la memoria del sistema, al tiempo que mantienes un rendimiento similar al de la ejecución en memoria.

4. Formato de archivo y rendimiento de E/S

SQLite

SQLite almacena los datos en su formato propio basado en filas, que es portátil y estable, pero carece de interoperabilidad directa con los formatos analíticos modernos. A menudo, los datos deben importarse a SQLite antes de que se puedan ejecutar las consultas, lo que añade una sobrecarga adicional de E/S.

DuckDB

DuckDB admite de forma nativa múltiples formatos de archivo, incluidos Parquet, Arrow y CSV, lo que te permite consultar datos directamente sin necesidad de conversión (por ejemplo, SELECT … FROM 'file.parquet').

Esto elimina la sobrecarga de ETL y acelera el análisis al leer solo los datos necesarios de formatos columnares como Parquet.

Ingestión de datos e interoperabilidad en DuckDB frente a SQLite

Las bases de datos se utilizan habitualmente para ingestar grandes cantidades de datos. A continuación, analizaremos cómo se desempeñan cada uno de ellos en cuanto a capacidades de ingestión e interoperabilidad.

1. Formatos de archivo compatibles e ingestión

DuckDB

DuckDB ofrece ingestión nativa de Parquet, Arrow y CSV. Puede ejecutar consultas SQL directamente en Parquet sin importarlas a un archivo de base de datos.

import duckdb

con = duckdb.connect()
result = con.execute("""
    SELECT customer_id, SUM(amount) AS total_spent
    FROM 'sales.parquet'
    GROUP BY customer_id
    ORDER BY total_spent DESC
    LIMIT 5
""").fetchdf()

print(result)

SQLite

SQLite requiere importar datos externos a su formato de almacenamiento antes de poder ejecutar consultas.

import sqlite3
import pandas as pd

# Load CSV into pandas first
df = pd.read_csv("sales.csv")

# Store into SQLite
conn = sqlite3.connect("sales.db")
df.to_sql("sales", conn, if_exists="replace", index=False)

# Query the imported table
cursor = conn.execute("""
    SELECT customer_id, SUM(amount) AS total_spent
    FROM sales
    GROUP BY customer_id
    ORDER BY total_spent DESC
    LIMIT 5
""")

print(cursor.fetchall())

2. Integración con herramientas de ciencia de datos

DuckDB

DuckDB está estrechamente integrado con pandas, R y Jupyter, y se integra directamente con pandas DataFrame, lo que te permite tratarlos como tablas SQL:

import duckdb
import pandas as pd

# Example pandas DataFrame
df = pd.DataFrame({
    "customer_id": [1, 2, 1, 3],
    "amount": [100, 200, 150, 300]
})

# Query DataFrame directly with DuckDB
result = duckdb.query("""
    SELECT customer_id, AVG(amount) as avg_spent
    FROM df
    GROUP BY customer_id
""").to_df()

print(result)

SQLite

SQLite funciona con muchos lenguajes de programación, pero está menos centrado en la ciencia de datos.

Por ejemplo, SQLite también puede interactuar con pandas, pero normalmente requiere más código repetitivo.

import sqlite3
import pandas as pd

conn = sqlite3.connect(":memory:")
df = pd.DataFrame({
    "customer_id": [1, 2, 1, 3],
    "amount": [100, 200, 150, 300]
})

df.to_sql("sales", conn, index=False, if_exists="replace")

# Query back into pandas
query = "SELECT customer_id, AVG(amount) as avg_spent FROM sales GROUP BY customer_id"
result = pd.read_sql_query(query, conn)

print(result)

3. Enlaces de lenguaje y API

SQLite

SQLite existe desde el año 2000, por lo que sus enlaces son extremadamente maduros. Como se trata de una pequeña biblioteca C, la mayoría de los lenguajes cuentan con soporte oficial o comunitario.

Algunos ejemplos son: C, Python (sqlite3), Java, PHP y más.

DuckDB

DuckDB es mucho más reciente, pero se ha diseñado teniendo en cuenta los flujos de trabajo de ciencia de datos y análisis. Tus restricciones son menores, pero muy favorables para la ciencia de datos.

Algunos ejemplos son: Enlaces Python, R, C++ y JavaScript.

Casos de uso y ámbitos de aplicación

Aunque tanto SQLite como DuckDB son bases de datos integradas y ligeras, tienen fines muy diferentes. 

SQLite destaca en contextos transaccionales a nivel de aplicación, mientras que DuckDB está optimizado para cargas de trabajo analíticas en ciencia de datos e inteligencia empresarial. En algunos casos, incluso pueden complementarse entre sí.

Veamos algunos ejemplos concretos a continuación:

1. Escenarios de aplicación de SQLite

SQLite es muy ligero, lo que lo hace perfecto para:

  • Almacenamiento de aplicaciones móviles: SQLite es la base de datos predeterminada para aplicaciones Android e iOS, y proporciona almacenamiento local persistente sin necesidad de un servidor backend.
  • Dispositivos IoT: Los dispositivos IoT ligeros suelen basarse en SQLite debido a su mínimo impacto y a que no requieren configuración.
  • Almacenamiento en caché del navegador: SQLite se utiliza habitualmente como capa de caché en sistemas distribuidos o como almacén intermedio al transferir datos entre sistemas.

2. Aplicaciones analíticas de DuckDB

DuckDB está estrechamente vinculado a flujos de trabajo analíticos como los procesos ETL. Aquí tienes un ejemplo de cómo se puede implementar en Python.

Uso de la CLI de DuckDB:

-- Connect / create DB
ATTACH 'warehouse.duckdb' AS wh; USE wh;

-- EXTRACT: read a CSV
CREATE OR REPLACE VIEW v_orders AS
SELECT * FROM read_csv_auto('data/orders.csv');  -- order_id, customer_id, order_ts, status, amount

-- TRANSFORM: clean types + derive metrics
WITH cleaned AS (
  SELECT
    CAST(order_id AS BIGINT)              AS order_id,
    CAST(customer_id AS BIGINT)           AS customer_id,
    TRY_CAST(order_ts AS TIMESTAMP)       AS order_ts,
    COALESCE(NULLIF(status,''),'unknown') AS status,
    TRY_CAST(amount AS DOUBLE)            AS amount
  FROM v_orders
),
agg AS (
  SELECT DATE_TRUNC('day', order_ts) AS order_date,
         SUM(amount)                 AS daily_gmv,
         COUNT(*)                    AS orders
  FROM cleaned
  GROUP BY 1
)
-- LOAD: upsert curated tables + export parquet
CREATE TABLE IF NOT EXISTS fact_orders AS SELECT * FROM cleaned WHERE 1=0;
MERGE INTO fact_orders t USING cleaned s
ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET
  customer_id=s.customer_id, order_ts=s.order_ts, status=s.status, amount=s.amount
WHEN NOT MATCHED THEN INSERT VALUES
  (s.order_id, s.customer_id, s.order_ts, s.status, s.amount);

COPY agg TO 'warehouse/daily_gmv' (FORMAT PARQUET, PARTITION_BY (order_date), OVERWRITE_OR_IGNORE 1);

Ahora ejecuta el archivo en la terminal:

duckdb -c ".read etl.sql"

Como alternativa, también puedes utilizar DuckDB dentro de Python para optimizar el flujo de trabajo del análisis de datos.

import duckdb, pathlib
db = pathlib.Path("warehouse.duckdb")
con = duckdb.connect(str(db))

# EXTRACT
con.execute("""
CREATE OR REPLACE VIEW v_orders AS
SELECT * FROM read_csv_auto('data/orders.csv')
""")

# TRANSFORM
con.execute("""
CREATE OR REPLACE VIEW v_clean AS
SELECT CAST(order_id AS BIGINT) order_id,
       CAST(customer_id AS BIGINT) customer_id,
       TRY_CAST(order_ts AS TIMESTAMP) order_ts,
       COALESCE(NULLIF(status,''),'unknown') status,
       TRY_CAST(amount AS DOUBLE) amount
FROM v_orders
""")

# LOAD (table + parquet export)
con.execute("CREATE TABLE IF NOT EXISTS fact_orders AS SELECT * FROM v_clean WHERE 1=0")
con.execute("""
MERGE INTO fact_orders t USING v_clean s
ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET customer_id=s.customer_id, order_ts=s.order_ts, status=s.status, amount=s.amount
WHEN NOT MATCHED THEN INSERT VALUES (s.order_id, s.customer_id, s.order_ts, s.status, s.amount)
""")
con.execute("""
COPY (SELECT DATE_TRUNC('day', order_ts) AS order_date, SUM(amount) AS daily_gmv FROM fact_orders GROUP BY 1)
TO 'warehouse/daily_gmv' (FORMAT PARQUET, PARTITION_BY (order_date), OVERWRITE_OR_IGNORE 1)
""")

3. Escenarios híbridos y complementarios

Analizar datos SQLite en DuckDB:

DuckDB puede consultar directamente los datos dentro de un archivo de base de datos SQLite:

import duckdb

# Query a SQLite database via the sqlite_scanner extension
con = duckdb.connect()
con.install_extension("sqlite_scanner")
con.load_extension("sqlite_scanner")

result = con.execute("""
    SELECT customer_id, COUNT(*) AS orders
    FROM sqlite_scan('app_cache.db', 'orders')
    GROUP BY customer_id
    ORDER BY orders DESC
""").fetchdf()

print(result)

Optimización del rendimiento y mejores prácticas

Tanto SQLite como DuckDB son eficientes por diseño, pero su rendimiento puede variar mucho dependiendo de cómo se ingesten, consulten y mantengan los datos.

1. Inserciones masivas y gestión eficiente de datos

SQLite

Para cargas de datos grandes, utiliza siempre transacciones. Insertar filas una por una sin una transacción obliga a SQLite a confirmar cada fila individualmente, lo que ralentiza considerablemente el rendimiento.

import sqlite3

conn = sqlite3.connect("perf.db")
cur = conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS logs (id INTEGER, message TEXT)")

# Bulk insert with a single transaction
data = [(i, f"event {i}") for i in range(100000)]
cur.execute("BEGIN TRANSACTION;")
cur.executemany("INSERT INTO logs VALUES (?, ?)", data)
conn.commit()

Agrupar los datos como en el ejemplo anterior mejora significativamente el rendimiento.

DuckDB

DuckDB gestiona de forma eficiente la ingesta de grandes conjuntos de datos, especialmente desde archivos externos. Utiliza comandos de COPY o consultas directas de Parquet/CSV para acelerar los procesos.

import duckdb
con = duckdb.connect()
# Bulk load CSV into DuckDB
con.execute(""" CREATE OR REPLACE TABLE logs AS SELECT * FROM read_csv_auto('transactions.csv') """)

2. Técnicas de optimización de consultas

SQLite

Para optimizar mejor tus consultas, utiliza índices para las búsquedas.

CREATE INDEX idx_customer_id ON orders(customer_id);

Recomendaría utilizar EXPLAIN QUERY PLAN para analizar las rutas de ejecución e identificar los índices que faltan.

En general, intenta que las consultas sean sencillas y evita las uniones innecesarias en entornos con recursos limitados.

DuckDB

Para DuckDB, puedes utilizar la poda de columnas y el empuje de predicados.

  • Poda de columnas: DuckDB solo lee las columnas que realmente necesita tu consulta. Esto se traduce en menos E/S y escaneos más rápidos, especialmente con tablas amplias o archivos Parquet.
  • Empuje de predicados: DuckDB aplica tus filtros WHERE al escaneo de tablas/archivos para que pueda omitir grupos de filas/páginas/archivos que no coincidan. Esto lleva a leer muchos menos bytes utilizando estadísticas de archivos/particiones (por ejemplo, mínimo/máximo de Parquet).

Ejemplo de poda de columnas:

-- Only reads the 'user_id' and 'amount' columns; other columns aren’t touched
SELECT user_id, SUM(amount)
FROM read_parquet('events/*.parquet')
GROUP BY user_id;

Ejemplo de predicado pushdown (Parquet):

-- Skips row groups/pages whose min/max(order_ts) are entirely outside this range
SELECT *
FROM read_parquet('events/dt=*/events.parquet')
WHERE order_ts >= TIMESTAMP '2025-09-01'
  AND order_ts <  TIMESTAMP '2025-10-01';

3. Consideraciones sobre mantenimiento y funcionamiento

  • SQLite: Operaciones regulares de « VACUUM » para recuperar espacio. Para aplicaciones integradas, asegúrate de que haya suficiente E/S de disco y utiliza el modo WAL para obtener una mayor durabilidad y acceso simultáneo.
  • DuckDB: Optimizado para análisis; requiere un ajuste mínimo. Organiza grandes conjuntos de datos en archivos Parquet particionados para aprovechar la poda de particiones.Compara regularmente las consultas con cargas de trabajo de muestra para ajustar la configuración del paralelismo (a través de PRAGMA threads).

Desarrollo, integración y ecosistema

Las bases de datos deben estar bien integradas para garantizar que se pueda acceder fácilmente a los datos. Ahora veremos cómo se integra cada base de datos con otros sistemas.

1. Compatibilidad con lenguajes de programación y API

  • SQLite: Amplia compatibilidad lingüística. Ofrece una de las gamas más amplias de enlaces de idiomas en el mundo de las bases de datos. Existen controladores oficiales y mantenidos por la comunidad para Python, Java, C#, C/C++, PHP, Go, Ruby, Rust y más de 30 otros.
  • DuckDB: Sólidas integraciones de ciencia de datos. Se centra en enlaces orientados a la ciencia de datos: compatibilidad oficial con Python, R y C/C++.

2. Integración de la ciencia de datos y el análisis

DuckDB: Funciona directamente con DataFrame de pandas.

Ejemplo:

import duckdb 
import pandas as pd

df = pd.DataFrame({"x": [1,2,3], "y": [10,20,30]})
duckdb.query("SELECT AVG(y) FROM df").show()

DuckDB también admite funciones definidas por el usuario (UDF) en SQL y Python, lo que permite realizar análisis avanzados y transformaciones personalizadas.

Ejemplo (UDF de Python en DuckDB):

import duckdb
import math

con = duckdb.connect()

# Register a Python function as UDF
con.create_function("sqrt_plus", lambda x: math.sqrt(x) + 1)

result = con.execute("SELECT sqrt_plus(16)").fetchall()
print(result)  # [(5.0,)]

3. Integración de la nube y la infraestructura

SQLite

SQLite es una base de datos local diseñada principalmente para el almacenamiento local e integrado.

Se utiliza en aplicaciones nativas de la nube como capa de persistencia ligera o caché, a menudo dentro de contenedores. Aunque carece de conectores directos de almacenamiento en la nube, las bases de datos SQLite son portátiles y se pueden transferir fácilmente entre entornos.

DuckDB

DuckDB está experimentando una creciente adopción en la nube (consultando archivos S3 Parquet) debido a su optimización para las arquitecturas de datos modernas.

También ofrece compatibilidad nativa para consultar formatos de almacenamiento en la nube, como archivos Parquet y Arrow en AWS S3, Azure Blob Storageo Google Cloud Storage.

DuckDB se adapta bien a los escenarios de análisis sin servidor, en los que los datos se almacenan en un almacén de objetos y se consultan bajo demanda sin necesidad de un almacén pesado.

Limitaciones y compensaciones

A pesar de sus puntos fuertes, tanto DuckDB como SQLite tienen limitaciones inherentes relacionadas con vuestras filosofías de diseño. 

  • Restricciones de concurrencia y escalabilidad:
    • SQLite: Concurrencia de escritura limitada.
    • DuckDB: Modelo de concurrencia de un solo proceso.
  • Limitaciones de memoria y gestión de recursos:
    • SQLite: Ligero, pero no puede escalarse a conjuntos de datos muy grandes.
    • DuckDB: Puede volcarse al disco, pero no está diseñado para la durabilidad transaccional a gran escala.
  • Características y funcionalidades que faltan:
    • SQLite: Funciones analíticas limitadas.
    • DuckDB: Robustez transaccional limitada.
  • Compromisos y limitaciones en cuanto al rendimiento:
    • SQLite: Rápido para las transacciones, lento para los análisis.
    • DuckDB: Rápido para análisis, más lento para escrituras pequeñas.

SQLite frente a DuckDB: reflexiones finales

DuckDB y SQLite desempeñan funciones valiosas pero distintas:

  • Elige SQLite si necesitas una base de datos transaccional sencilla y ligera para aplicaciones y sistemas integrados.
  • Elige DuckDB si necesitas análisis de alto rendimiento directamente en tus flujos de trabajo de Python/R.

En muchos casos, se complementan entre sí: SQLite para almacenamiento y transacciones, DuckDB para consultas analíticas sobre esos datos. La elección correcta depende de si tu carga de trabajo es más OLTP (transacciones) u OLAP (análisis).

¿Quieres saber más sobre bases de datos como DuckDB y SQLite? Echa un vistazo a nuestra tutorial Guía para principiantes de SQLite y nuestra Introducción a DuckDB SQL.

Preguntas frecuentes sobre DuckDB frente a SQLite

¿Cómo maneja DuckDB los conjuntos de datos más grandes que la memoria?

DuckDB utiliza un motor de ejecución vectorizado y puede volcar los resultados intermedios al disco cuando las consultas superan la RAM disponible. Esto te permite procesar conjuntos de datos mucho más grandes que la memoria, manteniendo un rendimiento razonable, aunque la velocidad depende en gran medida de la E/S del disco.

¿Cuáles son las principales diferencias de rendimiento entre DuckDB y SQLite?

SQLite está optimizado para cargas de trabajo transaccionales (OLTP) y destaca en pequeñas inserciones, actualizaciones y búsquedas de una sola fila. Por otro lado, DuckDB está optimizado para cargas de trabajo analíticas (OLAP), con agregaciones, uniones y exploraciones más rápidas en grandes conjuntos de datos gracias a su diseño columnar y su ejecución paralela.

¿Se puede utilizar DuckDB para realizar análisis en tiempo real?

DuckDB es más adecuado para análisis por lotes o interactivos, no para flujos continuos en tiempo real. Puede analizar datos nuevos rápidamente si se ingieren o se accede a ellos desde archivos, pero carece de las capacidades integradas de transmisión y ingestión de alta frecuencia que se encuentran en los sistemas dedicados en tiempo real.

¿Cómo mejora el almacenamiento en columnas de DuckDB el rendimiento de las consultas?

El almacenamiento columnar permite a DuckDB leer solo las columnas necesarias para una consulta, lo que reduce la sobrecarga de E/S. En combinación con la compresión y la ejecución vectorizada, esto mejora la eficiencia de la caché y acelera operaciones como las agregaciones y los filtros en grandes conjuntos de datos.

¿Cuáles son las limitaciones del uso de DuckDB para cargas de trabajo transaccionales de alta concurrencia?

DuckDB no está diseñado para sistemas transaccionales multiusuario. Admite transacciones ACID, pero su modelo de concurrencia es limitado, lo que lo hace inadecuado para entornos con muchos escritores simultáneos o actualizaciones de alta frecuencia. SQLite o una base de datos basada en servidor es mejor para esos casos.


Austin Chia's photo
Author
Austin Chia
LinkedIn

Soy Austin, bloguero y escritor técnico con años de experiencia como científico de datos y analista de datos en el sector sanitario. Empecé mi andadura tecnológica con una formación en biología, y ahora ayudo a otros a hacer la misma transición a través de mi blog tecnológico. Mi pasión por la tecnología me ha llevado a escribir para decenas de empresas de SaaS, inspirando a otros y compartiendo mis experiencias.

Temas

Los mejores cursos de DataCamp

Curso

Introduction to Databases in Python

4 h
99.5K
In this course, you'll learn the basics of relational databases and how to interact with them.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado

blog

SQL Server, PostgreSQL, MySQL... ¿cuál es la diferencia? ¿Por dónde empiezo?

En este tutorial, aprenderás algunas de las diferencias básicas entre los dialectos SQL y por dónde deberías empezar.
Mona Khalil's photo

Mona Khalil

5 min

SQLAlchemy_Tutorial.

Tutorial

Tutorial de SQLAlchemy con ejemplos

Aprende a acceder y ejecutar consultas SQL en todo tipo de bases de datos relacionales utilizando objetos Python.
Abid Ali Awan's photo

Abid Ali Awan

Tutorial

Introducción a los disparadores SQL: Guía para desarrolladores

Aprende a utilizar los disparadores SQL para automatizar tareas, mantener la integridad de los datos y mejorar el rendimiento de la base de datos. Prueba ejemplos prácticos como los comandos CREATE, ALTER y DROP en MySQL y Oracle.
Oluseye Jeremiah's photo

Oluseye Jeremiah

Tutorial

Ejemplos y tutoriales de consultas SQL

Si quiere iniciarse en SQL, nosotros le ayudamos. En este tutorial de SQL, le presentaremos las consultas SQL, una potente herramienta que nos permite trabajar con los datos almacenados en una base de datos. Verá cómo escribir consultas SQL, aprenderá sobre
Sejal Jaiswal's photo

Sejal Jaiswal

Tutorial

Seleccionar varias columnas en SQL

Aprende a seleccionar fácilmente varias columnas de una tabla de base de datos en SQL, o a seleccionar todas las columnas de una tabla en una simple consulta.
DataCamp Team's photo

DataCamp Team

Tutorial

Tutorial sobre cómo ejecutar consultas SQL en Python y R

Aprenda formas fáciles y eficaces de ejecutar consultas SQL en Python y R para el análisis de datos y la gestión de bases de datos.
Abid Ali Awan's photo

Abid Ali Awan

Ver másVer más