dlt inclut des optimisations spécifiques à BigQuery. Les deux stratégies de chargement, le bigquery_adapter, la gestion des JSON imbriqués et les tables de métadonnées créées par dlt influencent tous la conception et l’exploitation des pipelines.
Configuration
Installez dlt avec les extras BigQuery :
pip install "dlt[bigquery]"La configuration se trouve dans secrets.toml — la convention de dlt pour garder les credentials hors du code :
[destination.bigquery]project_id = "your-project"private_key = "-----BEGIN PRIVATE KEY-----\n..."client_email = "sa@your-project.iam.gserviceaccount.com"Le compte de service a besoin au minimum des rôles BigQuery Data Editor et BigQuery Job User. Pour le staging GCS (couvert ci-dessous), il a également besoin de Storage Object Creator sur le bucket de staging.
Deux stratégies de chargement
dlt offre deux façons d’injecter des données dans BigQuery. Le choix a des implications significatives en termes de coût.
Streaming inserts
Les streaming inserts poussent les lignes directement dans les tables BigQuery au moment du chargement. Les données sont immédiatement interrogeables — les lignes apparaissent dans les tables en quelques secondes. C’est la configuration la plus simple et elle fonctionne bien pour les cas d’usage à faible latence où la fraîcheur importe plus que le coût.
Le problème : l’API de streaming insert de BigQuery coûte 0,01 $ par 200 Mo. Pour les petits datasets, c’est négligeable. Pour tout ce qui déplace des gigaoctets quotidiennement — données marketing, flux d’événements, APIs à fort volume — les coûts de streaming insert s’accumulent et doivent être intégrés dans votre décision. Voir Modèle de coût BigQuery pour comprendre pourquoi les coûts du chargement par lot vs. streaming insert importent à grande échelle.
Staging GCS
Le staging GCS évite entièrement les coûts de streaming insert. Au lieu de pousser les lignes directement, dlt :
- Télécharge les données dans un bucket Cloud Storage sous forme de fichiers Parquet ou JSONL
- Émet une commande BigQuery
LOAD DATAqui lit depuis GCS
Le chargement par lot BigQuery depuis GCS est gratuit. Vous payez pour le stockage GCS (trivial pour les fichiers de staging) et la requête BigQuery qui les charge. Pour les grands datasets ou les pipelines qui s’exécutent fréquemment, la différence de coût entre les streaming inserts et le staging GCS est substantielle.
Configurez le staging en spécifiant un bucket de staging dans votre pipeline :
pipeline = dlt.pipeline( pipeline_name="my_pipeline", destination="bigquery", staging="filesystem", # utiliser le staging GCS dataset_name="raw_data")Et dans config.toml :
[destination.filesystem]bucket_url = "gs://your-staging-bucket"Pour tout pipeline au-delà des petits datasets, le staging GCS est le bon défaut. La surcharge opérationnelle est minimale et les économies de coûts sont réelles.
Partitionnement et clustering avec bigquery_adapter
La fonction bigquery_adapter() expose les optimisations de tables spécifiques à BigQuery que dlt ne peut pas inférer seul à partir de vos données :
from dlt.destinations.adapters import bigquery_adapter
@dlt.resourcedef events(): yield from get_events()
# Partitionner par date, clusterer par user_idbigquery_adapter( events, partition="event_date", cluster=["user_id"])Cela configure le partitionnement et le clustering de manière déclarative dans le cadre de la définition du pipeline — pas comme une étape DDL séparée ou une opération post-chargement.
Le partitionnement divise la table en segments par valeur de colonne, typiquement une date. BigQuery ne lit que les partitions correspondant aux filtres de votre clause WHERE, ce qui réduit considérablement les coûts de scan pour les requêtes par plage temporelle. Pour toute grande table de faits (événements, transactions, réponses API avec timestamps), le partitionnement par date devrait être standard.
Le clustering trie les données dans les partitions selon des colonnes spécifiées. Les requêtes qui filtrent sur les colonnes clusterisées scannent moins de données, même au sein d’une partition. Pour les données marketing, le clustering sur campaign_id ou ad_group_id réduit les coûts de scan pour les requêtes filtrées que les analystes exécutent le plus.
Les deux sont de la configuration, pas du travail d’ingénierie. Les assistants IA gèrent cela correctement du premier coup une fois que vous leur avez dit sur quoi partitionner et clusterer. Voir Cadre de décision partitionnement vs. clustering pour le raisonnement sur le choix des colonnes.
Normalisation des JSON imbriqués
Les APIs retournent du JSON imbriqué. Les tables relationnelles ne supportent pas l’imbrication. dlt fait le pont automatiquement.
Une réponse API comme :
{ "id": 1, "name": "Alice", "addresses": [ {"city": "Berlin", "country": "DE"}, {"city": "Paris", "country": "FR"} ]}Devient deux tables dans BigQuery :
users— avecid,nameet les colonnes de métadonnées dltusers__addresses— aveccity,country,_dlt_id(l’identifiant de la ligne parente) et_dlt_parent_id
Les colonnes _dlt_id et _dlt_parent_id sont les clés référentielles de dlt. Vous effectuez des JOIN dessus pour reconstruire les structures imbriquées en SQL quand vous en avez besoin.
Vous contrôlez la profondeur d’imbrication avec max_table_nesting. La valeur par défaut crée une table enfant pour chaque niveau d’imbrication, ce qui peut produire une prolifération de tables pour les réponses profondément imbriquées :
@dlt.resource(max_table_nesting=2)def users(): yield from get_users()Définir max_table_nesting=2 ou max_table_nesting=3 crée des schémas lisibles sans prolifération excessive de tables. Tout ce qui dépasse 3 niveaux indique généralement que la réponse API devrait être aplatie avant d’atteindre dlt.
Tables de métadonnées
dlt crée trois tables de métadonnées dans votre dataset. Elles sont préfixées par _dlt_ et contiennent des informations opérationnelles sur le pipeline :
_dlt_loads trace chaque exécution du pipeline — quand il s’est exécuté, quelles ressources ont été chargées, combien de lignes ont été traitées, et si le chargement a réussi. C’est votre premier arrêt pour déboguer les problèmes de pipeline.
_dlt_pipeline_state stocke l’état du chargement incrémental — les valeurs de curseur qui indiquent à dlt où chaque ressource s’est arrêtée. Si vous déboguez pourquoi un pipeline incrémental ne récupère pas de nouvelles données, interrogez d’abord cette table. Voir Chargement incrémental dlt pour comprendre comment fonctionne le suivi d’état.
_dlt_version enregistre quelle version de dlt a exécuté chaque chargement et la version du schéma à ce moment. Utile pour résoudre les problèmes d’évolution du schéma.
Ces tables sont créées automatiquement. Vous n’avez pas besoin de les provisionner. Elles sont interrogeables comme n’importe quelle autre table BigQuery, et puisqu’elles se trouvent dans le même dataset que vos données, elles sont immédiatement visibles dans n’importe quelle console BigQuery ou outil SQL.
Ce que cela signifie en pratique
Pour les analytics engineers qui exécutent dbt par-dessus des données chargées par dlt, la configuration pratique ressemble à ceci :
- dlt charge les données API brutes dans un dataset
rawavec staging GCS bigquery_adapter()configure le partitionnement et le clustering au moment du chargement- Le JSON imbriqué se déploie en tables parent-enfant automatiquement
- Les sources dbt référencent les tables créées par dlt, les tables
_dlt_incluses si vous avez besoin des métadonnées de pipeline dans vos modèles
Les tables de métadonnées dlt sont particulièrement utiles pour les vérifications de fraîcheur — interrogez _dlt_loads pour déterminer quand une source a été synchronisée avec succès pour la dernière fois, et exposez-le dans les tests de fraîcheur dbt ou les politiques de fraîcheur Dagster.
Pour l’image complète de la construction de pipelines dlt, commencez par Concepts fondamentaux de dlt. Pour la façon dont le chargement incrémental interagit avec les coûts BigQuery, voir Chargement incrémental dlt et Modèle de coût BigQuery.