À 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, PostgreSQL, DuckDB, Polars… c'est quoi la différence ?

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 :

python
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

  1. Installer DuckDB

    Avec UV :

    bash
    uv add duckdb

    Il y a aussi un binaire CLI duckdb qu'on peut installer séparément (style psql) pour des requêtes ad-hoc en terminal.

  2. En mémoire ou en fichier

    python
    import 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()
  3. Lire des CSV et Parquet directement

    Le superpouvoir de DuckDB : les fichiers sont des tables. Pas besoin de CREATE TABLE ni d'import.

    python
    duckdb.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
  4. Requêter un DataFrame pandas ou Polars

    Tu peux mélanger SQL et DataFrames librement :

    python
    import 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.

  5. Créer, charger, sauvegarder une table

    python
    con = 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)
    """)
  6. 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.

    python
    con.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")
  7. Utiliser le CLI pour de l'ad-hoc

    bash
    duckdb                                # 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

python (one-shot)
import duckdb
duckdb.sql("SELECT * FROM 'data.parquet' LIMIT 5").df()
duckdb.sql("SELECT * FROM 'data/*.csv'").df()
python (connexion persistante)
con = duckdb.connect("db.duckdb")
con.sql("CREATE TABLE t AS SELECT * FROM 'f.parquet'")
con.sql("SELECT * FROM t").df()
con.close()
python (DataFrame ↔ SQL)
df = pd.read_csv("…")
duckdb.sql("SELECT * FROM df WHERE x > 0").df()
duckdb.sql("…").pl()       # Polars
bash (CLI)
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 %sql qui 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.
Quand DuckDB plutôt que Polars (ou inversement) ?

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