DuckDB
Le « SQLite de l'analytique » : une base de données SQL dans un fichier (ou même en mémoire), conçue pour aller vite sur des requêtes analytiques. Capable de lire un Parquet ou un CSV directement, sans import préalable, en quelques millions de lignes par seconde.
À quoi ça sert
DuckDB se positionne entre SQLite et un vrai data warehouse :
- Comme SQLite, c'est une base embarquée dans un fichier (ou en mémoire) — pas de serveur à lancer, pas d'install de Postgres.
- Comme PostgreSQL, c'est du SQL complet et standard (CTE, fenêtres, JSON…).
- Comme Polars, le moteur est vectorisé et orienté colonne, ce qui le rend ultra-rapide sur des agrégations.
Cas typiques où DuckDB est l'outil parfait :
- Analyser un gros CSV / Parquet en SQL, sans l'importer dans une vraie base.
- Requêter des fichiers sur S3 / MinIO directement depuis du SQL — particulièrement puissant en data engineering.
- Pipelines de transformation (style dbt) en local avant de pousser vers un warehouse.
- Notebook exploratoire où on alterne SQL et pandas/Polars sans friction.
SQLite = base transactionnelle légère (OLTP), optimisée pour insertions/lectures aléatoires. PostgreSQL = base transactionnelle complète (multi-utilisateur, prod). DuckDB = base analytique (OLAP) embarquée, optimisée pour agréger des millions de lignes vite. Polars = même genre de moteur mais en API DataFrame Python plutôt que SQL. En pratique : SQLite/Postgres pour le stockage applicatif, DuckDB/Polars pour l'analyse.
Un exemple d'usage
Tu as un dossier de fichiers Parquet de ventes (un par mois, 50 Mo chacun). Tu veux le top 10 des produits sur toute la période, sans rien importer :
import duckdb
result = duckdb.sql("""
SELECT produit, SUM(montant) AS total
FROM 'ventes/*.parquet'
WHERE montant > 100
GROUP BY produit
ORDER BY total DESC
LIMIT 10
""").df()
print(result)
DuckDB scanne directement les fichiers Parquet (compressés, columnar),
ne lit que les colonnes produit et montant
(predicate/projection pushdown automatique), et renvoie un DataFrame
pandas. Pas d'import, pas de schéma à déclarer, pas de serveur.
How-to : installer et utiliser DuckDB
-
Installer DuckDB
Avec UV :
bashuv add duckdbIl y a aussi un binaire CLI
duckdbqu'on peut installer séparément (stylepsql) pour des requêtes ad-hoc en terminal. -
En mémoire ou en fichier
pythonimport duckdb # En mémoire (par défaut) con = duckdb.connect() # Persistant : un fichier .duckdb con = duckdb.connect("projet.duckdb") # Ou raccourci sans connexion explicite (in-memory) duckdb.sql("SELECT 42").show() -
Lire des CSV et Parquet directement
Le superpouvoir de DuckDB : les fichiers sont des tables. Pas besoin de
CREATE TABLEni d'import.pythonduckdb.sql("SELECT * FROM 'data.csv' LIMIT 5") duckdb.sql("SELECT * FROM 'data.parquet' LIMIT 5") # Plusieurs fichiers d'un coup duckdb.sql("SELECT * FROM 'logs/*.csv'") duckdb.sql("SELECT * FROM 'year=*/month=*/*.parquet'") # Hive partitioning -
Requêter un DataFrame pandas ou Polars
Tu peux mélanger SQL et DataFrames librement :
pythonimport pandas as pd import duckdb df = pd.read_csv("ventes.csv") # df est visible directement comme une table dans la requête result = duckdb.sql(""" SELECT produit, COUNT(*) AS n, AVG(montant) AS prix_moyen FROM df GROUP BY produit """).df() # renvoie un DataFrame pandas.df()renvoie pandas,.pl()renvoie Polars,.fetchall()renvoie une liste de tuples. -
Créer, charger, sauvegarder une table
pythoncon = duckdb.connect("projet.duckdb") # Créer une table à partir d'un fichier con.sql(""" CREATE TABLE ventes AS SELECT * FROM 'ventes.parquet' """) # Exporter une table en Parquet (compressé, rapide à relire) con.sql(""" COPY (SELECT * FROM ventes WHERE montant > 0) TO 'ventes_clean.parquet' (FORMAT PARQUET) """) -
Lire depuis S3 / MinIO
DuckDB sait lire directement depuis du stockage S3-compatible, comme MinIO. Très utile pour interroger des datasets stockés sur ton infra sans télécharger.
pythoncon.sql(""" INSTALL httpfs; LOAD httpfs; SET s3_endpoint='localhost:9000'; SET s3_access_key_id='…'; SET s3_secret_access_key='…'; SET s3_url_style='path'; SET s3_use_ssl=false; """) con.sql("SELECT * FROM 's3://bucket/data.parquet' LIMIT 10") -
Utiliser le CLI pour de l'ad-hoc
bashduckdb # shell interactif (in-memory) duckdb projet.duckdb # ouvre un fichier # Exécuter une requête one-shot duckdb -c "SELECT COUNT(*) FROM 'data.parquet'"Pourquoi Parquet plutôt que CSV ?Le format Parquet est columnar et compressé : DuckDB lit seulement les colonnes nécessaires à la requête, ignorant le reste. Sur un fichier 1 Go en CSV vs 100 Mo en Parquet, la requête peut être 10× plus rapide. Si tu fais beaucoup d'analytique, exporte une fois en Parquet, requête ensuite.
Aide-mémoire
import duckdb
duckdb.sql("SELECT * FROM 'data.parquet' LIMIT 5").df()
duckdb.sql("SELECT * FROM 'data/*.csv'").df()
con = duckdb.connect("db.duckdb")
con.sql("CREATE TABLE t AS SELECT * FROM 'f.parquet'")
con.sql("SELECT * FROM t").df()
con.close()
df = pd.read_csv("…")
duckdb.sql("SELECT * FROM df WHERE x > 0").df()
duckdb.sql("…").pl() # Polars
duckdb db.duckdb
duckdb -c "SELECT 1"
DuckDB et le reste de l'écosystème
- pandas / Polars — alliés naturels. DuckDB peut lire ces DataFrames directement comme des tables, et leur renvoyer un résultat de requête. Utile pour ajouter une couche SQL sur du code DataFrame existant.
- SQLite — DuckDB n'est pas un remplaçant : SQLite reste meilleur pour les bases applicatives (beaucoup d'insertions). DuckDB est meilleur pour l'analyse en lecture (agrégations sur des millions de lignes).
- PostgreSQL — DuckDB a une extension pour requêter Postgres comme une source. Pratique pour préparer un dashboard local sans charger le serveur Postgres.
-
MinIO — combo très
puissant : tes données vivent dans MinIO au format Parquet,
DuckDB les requête directement en SQL avec
INSTALL httpfs. -
Jupyter — DuckDB
a une extension
%sqlqui permet d'écrire du SQL directement dans une cellule sans wrapping Python. - SQLAlchemy — DuckDB a un driver SQLAlchemy, donc on peut le brancher comme backend d'un projet existant pour de l'analytique.
DuckDB et Polars sont très proches en perf et philosophie. Choisis DuckDB si tu préfères écrire du SQL (avec joins, CTE, window functions) — c'est l'outil parfait pour quelqu'un qui pense SQL. Choisis Polars si tu préfères une API DataFrame Python chainée — moins verbeux pour les transformations en plusieurs étapes. Tu peux aussi mélanger les deux.
Pour aller plus loin
- Site officiel : duckdb.org
- Documentation : duckdb.org/docs
- « Friendlier SQL with DuckDB » : duckdb.org/docs/sql/dialect/friendly_sql.html
- Cookbook Python : duckdb.org/docs/api/python/overview