Si vous exécutez dbt sur BigQuery, la gestion des slots requiert une attention particulière. Le pattern d’exécution de dbt — de nombreuses instructions SQL séquentielles — interagit avec les slots différemment d’une requête complexe unique ou d’une charge de travail de tableau de bord. Comprendre ces interactions est ce qui distingue un déploiement dbt bien optimisé d’un déploiement qui dépense trop en capacité ou souffre de ralentissements chroniques.
Pourquoi dbt est gourmand en calcul
Une exécution dbt typique peut exécuter des centaines de modèles. Chaque modèle est un job BigQuery séparé. Chaque job :
- Demande des slots à la réservation
- Potentiellement déclenche l’autoscaling
- Maintient les slots autoscalés pendant la fenêtre minimale de 60 secondes
- Se termine, libère les slots, puis le modèle suivant démarre
Pour une exécution séquentielle (un modèle à la fois), vous pouvez avoir un seul job en cours d’exécution, mais chacun peut déclencher une nouvelle fenêtre d’autoscaling. Pour une exécution parallèle (threads > 1), plusieurs jobs se disputent la capacité de votre réservation via le fair scheduling.
Les exécutions dbt intensives — en particulier les rafraîchissements complets de grands modèles — peuvent consommer une capacité de slots significative. Un rafraîchissement complet d’une table de faits de plusieurs téraoctets peut nécessiter 500+ slots pendant 30 minutes. Si cela s’exécute en même temps que vos modèles incrémentiels habituels, vous avez besoin d’une capacité suffisante pour les deux.
La fenêtre d’autoscaling de 60 secondes est particulièrement pertinente pour dbt. Considérez une exécution avec 200 modèles, chacun prenant 5 secondes. Avec l’autoscaling, chaque modèle qui déclenche une montée en charge maintient ces slots alloués pendant 60 secondes. Votre temps de slot facturé réel peut être 12 fois votre temps d’exécution de requête. C’est pourquoi le multiplicateur de coût d’autoscaling de 1,5x existe — le pattern de nombreuses petites requêtes de dbt est exactement la forme de charge de travail qui souffre du minimum de 60 secondes.
La limitation actuelle de dbt
À ce jour, dbt-bigquery utilise un seul projet pour les deux :
- Exécuter les requêtes (détermine quels slots de réservation sont utilisés)
- Stocker les tables de sortie
Il n’y a pas de moyen natif de dire « exécuter ce modèle en utilisant la réservation X ». Les issues GitHub #2918, #3708 et #1228 suivent les demandes de sélection de réservation à l’exécution, mais ce n’est pas encore implémenté.
Cela signifie que votre allocation de slots est entièrement déterminée par le projet GCP que dbt utilise, et ce projet est aussi l’endroit où vos tables arrivent. Vous ne pouvez pas (encore) séparer « où je veux le calcul » de « où je veux les données ».
Solution de contournement : projets séparés par charge de travail
La solution pratique est de multiple projets GCP, chacun assigné à une réservation appropriée. Cela s’aligne avec le pattern multi-projets qui est déjà une bonne pratique pour l’isolation des environnements.
jaffle_shop: target: prod outputs:
# Exécutions de production haute priorité prod: type: bigquery method: service-account project: mycompany-dbt-prod # Assigné à la réservation 'prod' (500 slots) dataset: analytics threads: 8
# Jobs batch/backfill batch: type: bigquery method: service-account project: mycompany-dbt-batch # Assigné à la réservation 'batch' (200 slots) dataset: analytics threads: 4
# Développement dev: type: bigquery method: service-account project: mycompany-dbt-dev # Tarification à la demande dataset: dev_adrienne threads: 4Puis exécutez avec la cible appropriée :
# Exécution incrémentielle de productiondbt run --target prod --select state:modified+
# Rafraîchissement complet en batchdbt run --target batch --full-refresh
# Itération de développementdbt run --target dev --select my_modelCela vous donne trois profils de capacité distincts. La production obtient des slots garantis pour les exécutions incrémentielles quotidiennes. Le batch obtient une réservation modérée pour les travaux intensifs mais non critiques en temps. Le développement reste en mode à la demande où vous payez par octet scanné et ne gaspillez pas la capacité réservée sur des commandes sporadiques.
Bonnes pratiques pour dbt + slots
1. Utilisez agressivement les modèles incrémentiels
Les modèles incrémentiels ne traitent que les données nouvelles/modifiées, réduisant drastiquement la consommation de slots par rapport aux rafraîchissements complets. Un modèle qui scanne 2 To lors d’un rafraîchissement complet peut scanner 20 Go de façon incrémentielle. C’est 100x moins de temps de slot.
2. Dimensionnez correctement vos threads
Plus de threads signifie plus de jobs concurrents et une demande de slots plus élevée. Faites correspondre votre paramètre threads à la capacité de votre réservation. Si vous avez 200 slots et exécutez 16 threads de modèles complexes, vous rencontrerez de la contention. Le fair scheduling divise l’allocation de slots de votre projet de manière égale entre les jobs concurrents — 200 slots / 16 threads = 12,5 slots par modèle. Ce n’est pas suffisant pour des transformations complexes.
Commencez avec threads: 4 et augmentez progressivement tout en surveillant l’utilisation des slots. Le point optimal dépend de la complexité des modèles et de la taille de la réservation.
3. Considérez la tarification à la demande pour le développement
Le travail de développement est imprévisible. La tarification à la demande signifie que vous ne gaspillez pas la capacité réservée sur des commandes dbt run sporadiques. Un développeur peut exécuter 5 modèles le matin, rien pendant 3 heures, puis un rafraîchissement complet d’un modèle de staging. La tarification à la demande gère cela sans aucune capacité inactive.
4. Définissez des baselines réalistes pour la production
Si votre dbt de production s’exécute à 6h chaque matin et utilise régulièrement 300 slots pendant 45 minutes, définissez la baseline à 300. Vous obtiendrez une capacité garantie quand vous en avez besoin. Laissez l’autoscaling gérer les pics occasionnels au-delà de 300.
Analysez votre utilisation de slots sur 30 jours avant de définir la baseline. L’utilisation au P50 (médiane) est un bon point de départ pour la baseline, avec une marge d’autoscaling au-dessus.
5. Surveillez l’utilisation des slots par modèle
dbt étiquète automatiquement les jobs quand il est configuré avec des labels de job. Interrogez INFORMATION_SCHEMA pour trouver vos modèles les plus coûteux :
SELECT (SELECT value FROM UNNEST(labels) WHERE key = 'dbt_invocation_id') AS invocation, (SELECT value FROM UNNEST(labels) WHERE key = 'dbt_model') AS model, COUNT(*) AS job_count, SUM(total_slot_ms) / 1000 / 60 AS total_slot_minutes, AVG(SAFE_DIVIDE(total_slot_ms, TIMESTAMP_DIFF(end_time, start_time, MILLISECOND))) AS avg_slotsFROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECTWHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) AND (SELECT value FROM UNNEST(labels) WHERE key = 'dbt_invocation_id') IS NOT NULLGROUP BY invocation, modelORDER BY total_slot_minutes DESCLIMIT 20;Cela révèle les modèles qui consomment le plus de temps de slot, en faisant d’eux les candidats prioritaires à l’optimisation. Appliquer le pruning de partition et les patterns SQL éprouvés à ces modèles produit souvent les meilleures améliorations.
6. Planifiez les travaux intensifs en dehors des heures de pointe
Si votre réservation BI partage la capacité inactive avec votre réservation de production via le partage de slots inactifs, planifiez les rafraîchissements complets et les backfills intensifs pendant les heures creuses de la BI. Vos jobs batch dbt empruntent les slots inactifs de la BI, et vos requêtes BI empruntent les slots inactifs de dbt. Des plannings complémentaires maximisent la valeur du partage de slots inactifs.