AccueilBlogTest technique DuckDB : SQL analytique in-process pour la data
Guide recrutement data

Test technique DuckDB : SQL analytique in-process pour la data

DuckDB est devenu l outil de référence pour l analyse locale sur des fichiers Parquet ou des DataFrames pandas. En entretien, on évalue la capacité à l utiliser comme moteur analytique puissant.

Data Builder·Juin 2025·6 min de lecture·Data Engineer · Data Scientist
Sommaire
  1. Pourquoi DuckDB
  2. SQL analytique avancé
  3. Requêter des fichiers Parquet
  4. Intégration pandas
  5. Optimisation et performance
  6. Cas d usage en production
  7. Grille

1Pourquoi DuckDB en 2025

Question discriminante

Dans quels cas DuckDB est-il préférable à pandas ou Spark ?

  • DuckDB vs pandas — 10-100x plus rapide sur les agrégations et les jointures. Exécution multi-thread native, pas de GIL
  • DuckDB vs Spark — pas de cluster à gérer, démarrage instantané, SQL natif complet. Idéal pour les fichiers < 100GB
  • DuckDB vs BigQuery/Snowflake — gratuit, local, zéro latence réseau. Pour les analyses exploratoires avant de passer au cloud
  • Cas d usage typique — analyser des dumps Parquet, prototype de transformation avant dbt, remplacement de pandas pour les analyses lourdes

2SQL analytique avancé dans DuckDB

Question discriminante

Quelles fonctionnalités SQL avancées DuckDB supporte-t-il nativement ?

import duckdb # DuckDB supporte tout le SQL analytique moderne conn = duckdb.connect() # PIVOT natif result = conn.execute(""" PIVOT orders ON region USING SUM(amount) GROUP BY YEAR(order_date) """).df() # UNPIVOT conn.execute(""" UNPIVOT wide_table ON (q1, q2, q3, q4) INTO NAME quarter VALUE revenue """) # LIST et MAP (types natifs) conn.execute(""" SELECT customer_id, LIST(product_id ORDER BY order_date) AS purchase_history, MAP(product_id, amount) AS amounts_by_product FROM orders GROUP BY customer_id """) # ASOF JOIN : jointure sur la valeur la plus proche conn.execute(""" SELECT o.*, p.price FROM orders o ASOF JOIN prices p ON o.product_id = p.product_id AND o.order_date >= p.effective_date """)

3Requêter des fichiers Parquet directement

Question discriminante

Comment requêtez-vous des fichiers Parquet sans les charger en mémoire ?

import duckdb # Requête directe sur des fichiers Parquet (glob supporté) result = duckdb.sql(""" SELECT region, YEAR(order_date) AS year, SUM(amount) AS revenue, COUNT(*) AS nb_orders FROM read_parquet('data/orders/year=*/month=*/*.parquet') WHERE order_date >= '2024-01-01' GROUP BY region, YEAR(order_date) ORDER BY revenue DESC """).df() # Predicate pushdown : DuckDB ne lit que les colonnes et lignes nécessaires # Beaucoup plus efficace que pd.read_parquet() suivi d un filtre # Créer une table virtuelle depuis Parquet duckdb.execute(""" CREATE VIEW orders_view AS SELECT * FROM read_parquet('data/orders/**/*.parquet') """) # Lire depuis S3 (nécessite le module httpfs) duckdb.install_extension('httpfs') duckdb.load_extension('httpfs') duckdb.execute("SET s3_region='eu-west-1'") result = duckdb.sql("SELECT * FROM 's3://mon-bucket/orders/*.parquet'").df()

4Intégration pandas : zero-copy avec Arrow

Question discriminante

Comment DuckDB communique-t-il avec pandas sans copier les données ?

import duckdb import pandas as pd df_orders = pd.read_csv('orders.csv') df_customers = pd.read_csv('customers.csv') # DuckDB peut requêter directement les DataFrames pandas # Via Apache Arrow (zero-copy) result = duckdb.sql(""" SELECT c.customer_name, c.segment, SUM(o.amount) AS total_revenue, COUNT(*) AS nb_orders FROM df_orders o JOIN df_customers c ON o.customer_id = c.customer_id GROUP BY c.customer_name, c.segment ORDER BY total_revenue DESC """).df() # Convertir vers différents formats result_arrow = duckdb.sql("SELECT * FROM df_orders").arrow() # PyArrow result_polars = duckdb.sql("SELECT * FROM df_orders").pl() # Polars result_numpy = duckdb.sql("SELECT amount FROM df_orders").numpy()

5Optimisation des performances DuckDB

Question discriminante

Quels sont les paramètres de configuration importants pour optimiser DuckDB ?

import duckdb conn = duckdb.connect() # Utiliser tous les coeurs disponibles conn.execute("SET threads TO 8") # Mémoire maximale (défaut : 80% de la RAM) conn.execute("SET memory_limit = '16GB'") # Spill to disk si nécessaire (pour les très gros datasets) conn.execute("SET temp_directory = '/tmp/duckdb_spill'") # Compression des résultats intermédiaires conn.execute("SET intermediate_result_chunk_cardinality = 2048") # Persistance : DuckDB peut aussi fonctionner en mode fichier conn_persistent = duckdb.connect('analytics.duckdb') conn_persistent.execute(""" CREATE TABLE IF NOT EXISTS orders AS SELECT * FROM read_parquet('data/orders/*.parquet') """)

6DuckDB en production : cas d usage

Question discriminante

Comment utilisez-vous DuckDB dans un pipeline de production ?

  • Script de transformation local — remplacer un script pandas lourd par DuckDB SQL. 10x moins de code, 100x plus rapide
  • Validation de données — vérifier la qualité d un dump Parquet avant de le charger dans BigQuery
  • Prototype de modèle dbt — tester la logique SQL localement avec DuckDB avant de déployer sur Snowflake
  • Analytics serverless — DuckDB + S3 comme stack analytics sans cluster. Coût quasi-nul pour des analyses ad-hoc
  • dbt avec DuckDB adapter — exécuter dbt localement avec DuckDB comme warehouse. Itérations ultra-rapides
import duckdb conn = duckdb.connect() # Lire directement depuis S3 sans telecharger conn.execute(""" INSTALL httpfs; LOAD httpfs; SET s3_region='eu-west-1'; SET s3_access_key_id='KEY'; SET s3_secret_access_key='SECRET'; """) result = conn.execute(""" SELECT region, SUM(amount) as revenue, COUNT(*) as orders FROM read_parquet('s3://bucket/orders/year=2025/**/*.parquet') WHERE order_date >= '2025-01-01' GROUP BY region ORDER BY revenue DESC """).df() # DuckDB comme ETL local conn.execute("CREATE TABLE orders AS SELECT * FROM read_csv_auto('orders.csv')") conn.execute("COPY (SELECT * FROM orders WHERE amount > 100) TO 'filtered.parquet' (FORMAT PARQUET)") # MotherDuck : DuckDB cloud partage import duckdb conn = duckdb.connect('md:mon_projet?motherduck_token=TOKEN')
  • OLAP columnar vectorise - DuckDB utilise un moteur vectorise en memoire. 10-100x plus rapide que pandas sur les agregations analytiques, sans JVM ni cluster
  • S3/GCS direct - lire des Parquet sur S3 sans telecharger. Predicate et projection pushdown : tire uniquement les colonnes et partitions necessaires
  • MotherDuck - DuckDB manage dans le cloud. Partager requetes et donnees sans infrastructure. Hybrid local/cloud
  • Cas d usage parfaits - exploration locale, ETL leger (moins de 50GB), tests de pipelines, remplacement de pandas pour l analytique, SQL dans notebooks
  • Limites - mono-noeud (pas de distribue), pas adapte aux workloads haute volumetrie Spark, pas de streaming natif

7Grille par niveau

NiveauMaitriseSignal GONO-GO
ConfirméSQL DuckDB basique, read_parquet, intégration pandasRemplace pandas par DuckDB pour les agrégations, utilise read_parquetN a jamais utilisé DuckDB
SeniorPIVOT/UNPIVOT natif, ASOF JOIN, S3, optimisationUtilise DuckDB en production, configure la mémoire et les threadsNe sait pas que DuckDB peut lire directement depuis S3

Vous recrutez un Data Engineer ou Data Scientist ?

Premier entretien gratuit. Rapport GO/NO-GO sous 48h.