Data Build Tool (dbt): guida ai componenti
Il Data Build Tool, o dbt, è uno strumento open-source che permette di iniziare a “costruire” dati in modo affidabile e scalabile. La sua caratteristica distintiva è il focus sulla fase di Trasformazione (T) del processo ELT (Extract, Load, Transform).
A differenza degli strumenti ETL tradizionali, infatti, dbt non estrae né carica dati. Assume che i dati grezzi (da API, database, ecc.) siano già stati caricati nel data warehouse (come Snowflake, BigQuery o Redshift) da strumenti come Fivetran, Airbyte o script custom.
Da quel momento sfrutta la potenza di calcolo del warehouse stesso per eseguire trasformazioni scritte in SQL.
L’obiettivo di dbt è applicare ai flussi di trasformazione dei dati le best practices dell’ingegneria del software:
- Controllo di versione (Git): l’intero processo di trasformazione è solo codice (
.sql,.yml,.py) e questo permette di eseguire code review, branching e CI/CD. - Test automatizzati: è possibile definire test di qualità e integrità (es.
not_null,unique, o logiche custom) che girano prima che i tuoi modelli vengano creati, garantendola validità del training set. - Modularità e riusabilità: con dbt, ogni trasformazione è un “modello” che può essere referenziato da altri, creando un grafo di dipendenze (DAG) chiaro e gestibile.
Per un Data Scientist o un Machine Learning Engineer, questo significa poter costruire in autonomia pipeline di feature engineering robuste e riproducibili. Invece di un notebook Jupyter che genera un CSV, è possibile definire un modello dbt che crea la feature table direttamente nel warehouse, documentata, testata e aggiornabile con un solo comando.
Anatomia di un Progetto dbt
L’intera logica di trasformazione risiede in file .sql e .yml, gestiti idealmente con Git. I file di configurazione principali che definiscono il progetto sono:
dbt_project.yml, ovvero il file di configurazione principale del progetto. Definisce il nome, le versioni e, soprattutto, i percorsi delle directory (es.model-paths: ["models"]).profiles.yml: questo file (che dovrebbe stare al di fuori del progetto, in ~/.dbt/) gestisce le connessioni al database. Contiene le credenziali, l’host e lo schema per i tuoi ambienti dev e prod e permette di separare la logica (il progetto) dalle credenziali (il profilo).
Il vero lavoro di trasformazione avviene all’interno della directory models/.
> Scopri anche il corso “SQL e gestione dei database relazionali”
I Modelli (models/) per il Feature Engineering
Un Modello in dbt non è altro che un singolo file .sql che contiene un’istruzione SELECT. Quando esegui dbt run, dbt prende questa SELECT e la materializza (come tabella o vista) nel data warehouse.
Per un Data Scientist, i modelli dbt risolvono il problema della scalabilità nel feature engineering. Invece di subire il collo di bottiglia del metodo tradizionale (estrarre i dati, caricarli in un DataFrame pandas con tutti i suoi limiti di memoria e salvare un .csv statico), si definisce semplicemente un modello dbt. Questo modello non fa altro che “insegnare” al data warehouse come creare la tabella di feature.
L’elemento che tiene insieme i modelli si chiama Grafo Aciclico Diretto delle dipendenze (DAG) e Dbt lo costruisce automaticamente in base a due funzioni Jinja fondamentali:
{{ source('nome_sorgente', 'nome_tabella') }}: fa riferimento a una tabella di dati grezzi (già caricata nel warehouse) definita nei file .yml. È il punto di partenza del DAG.{{ ref('nome_modello') }}: fa riferimento a un altro modello dbt. Questo crea una dipendenza e si assicura che dbt run esegua i modelli nell’ordine corretto.
Qui puoi trovare maggiori informazioni sulle funzioni ref e source: dbt Docs – About dbt models e dbt Docs – Sources.
Come vengono salvate le feature: le Materializzazioni
I modelli dbt non esistono nel warehouse finché non decidi come salvarli. La Materializzazione definisce come l’output della SELECT viene salvato. Le principali sono:
- view (default): veloce da creare. La query viene eseguita ogni volta che viene interrogata. Utile per logica intermedia che non è necessario memorizzare.
- table: memorizza fisicamente i risultati. Più lenta da creare, ma molto più veloce da interrogare. È la scelta ideale per le tabelle di feature finali o per i training set.
- incremental: aggiorna solo i record nuovi o modificati. È fondamentale quando la tua tabella di feature diventa troppo grande per essere ricostruita da zero ogni giorno.
- ephemeral: non viene materializzata. Viene compilata come Common Table Expression (CTE) nei modelli che la referenziano. Utile per “nascondere” logica di pulizia complessa senza ingombrare il database.
Puoi configurare la materializzazione direttamente nel file .sql: dbt Docs – Materializations
Validare il Training Set: test e qualità dei dati
Questa è una delle funzionalità più potenti di dbt per un Machine Learning Engineer. I Test servono a convalidare le assunzioni sui dati prima di avviare un training.
I test si definiscono in file .yml (spesso chiamati schema.yml) accanto ai tuoi modelli.
Esistono due tipi di test:
- Test Generici (Built-in): sono i più comuni e includono
not_null,unique,accepted_values(per campi categorici) erelationships(per l’integrità referenziale/foreign key). - Test Custom (Singolari): sono query SQL personalizzate (salvate nella directory tests/) che devono restituire zero righe per passare. Puoi usarli per logiche complesse (es. “nessun valore è oltre 3 deviazioni standard”).
Quando esegui dbt test, dbt controllerà tutti questi vincoli. Se, ad esempio, user_id non è univoco, il test fallirà, bloccando la pipeline CI/CD prima che il training set corrotto venga usato, risparmiando tempo e costi di calcolo.
> Leggi anche: “Machine Learning Engineer: competenze, compiti e responsabilità”
Scalabilità: codice DRY con macro e pacchetti
dbt inserisce il principio DRY (Don’t Repeat Yourself) tramite due componenti: Jinja e Macro.
Jinja (specificamente Jinja2) è un motore di templating che trasforma i file .sql da script statici a programmi dinamici. Permette di usare logica condizionale, cicli e variabili direttamente dentro SQL. La sintassi usa due tipi di delimitatori principali:
{{ ... }}Espressioni: usate per “stampare” un output. Le abbiamo già viste con{{ ref() }}e{{ source() }}. Vengono usate per richiamare variabili o eseguire macro.{% ... %}Istruzioni Logiche: usate per il controllo del flusso, come{% if ... %},{% for ... %}e soprattutto, per definire le macro.
Le Macro sono l’equivalente dbt delle funzioni in Python. Sono blocchi di logica SQL (e Jinja) riutilizzabili, definiti in file .sql all’interno della directory macros/. Permettono di centralizzare la logica di business o di trasformazione complessa in un unico punto.
Puoi trovare maggiori informazioni sulla sintassi delle Macro: dbt Docs – Jinja & Macros
I Pacchetti dbt (dbt Packages)
Il vero vantaggio arriva quando non si devono nemmeno scrivere le macro più comuni. I Pacchetti dbt sono repository Git che contengono modelli, test e (soprattutto) macro pre-costruite. Il pacchetto più indispensabile è dbt-utils, ovvero la “standard library” di dbt.
Per usarlo, crea un file packages.yml nella root del tuo progetto e aggiungi:
# packages.yml
packages:
- package: dbt-labs/dbt_utils
version: [">=1.0.0", "<1.2.0"] # Usa sempre un range di versioni
Esegui dbt deps (dependencies) per installarlo. Ora hai accesso a decine di macro testate dalla community.
Tracciare le feature nel tempo: gli Snapshots
Infine, dbt offre una funzionalità chiamata Snapshots (istantanee). Gli snapshot permettono di tracciare i cambiamenti in una tabella nel tempo, implementando le Slowly Changing Dimensions (SCD) di Tipo 2.
Per un Machine Learning Engineer, questa funzionalità è fondamentale per costruire training set point-in-time. Ad esempio, se vuoi sapere "qual era il segmento di questo cliente al momento in cui ha fatto l'acquisto?" (non qual è il suo segmento oggi), gli snapshot ti permettono di conservare questa cronologia completa delle modifiche, prevenendo il data leakage (fuga di dati) dal futuro.
Qui trovi la documentazione per gli Snapshots: dbt Docs - Snapshots
Il futuro: il dbt Semantic Layer (MetricFlow)
Quando il tuo notebook Python calcola il "Tasso di Churn" in un modo, mentre la dashboard di Tableau del team di marketing lo calcola in un altro, qual è la verità? Questo problema di duplicazione della logica è ciò che il dbt Semantic Layer (ora integrato con il motore MetricFlow) si propone di risolvere.
L'obiettivo è creare un livello di astrazione centralizzato sopra i modelli dbt: questo garantisce che, sia che si stia facendo un'analisi esplorativa in un notebook, sia che un'applicazione stia monitorando le prestazioni del modello, la definizione della metrica sia identica e coerente ovunque.
Qui trovi maggiori informazioni sui concetti del Semantic Layer e MetricFlow: dbt Docs - About the dbt Semantic Layer
Per un Data Scientist o un Machine Learning Engineer, dbt offre autonomia: fornisce il framework per costruire pipeline di feature engineering scalabili, testate e riproducibili che vivono dove vivono i tuoi dati: nel data warehouse.
Infine, la domanda non è se usare dbt, ma come. La scelta si riduce a due edizioni che condividono lo stesso motore:
- dbt Core: la versione open-source e a riga di comando (CLI). L’opzione corretta quando è necessario integrare dbt in una pipeline CI/CD o MLOps complessa esistente (es. GitLab CI, Jenkins, Airflow) e il team è in grado di gestire l'infrastruttura di orchestrazione e scheduling. È gratuito e infinitamente flessibile.
- dbt Cloud: la piattaforma SaaS completamente gestita. L’opzione corretta se il team vuole muoversi velocemente. Include un IDE basato sul web, scheduling nativo (eliminando la necessità di Airflow solo per dbt), integrazione CI/CD out-of-the-box e l'accesso più semplice alle funzionalità avanzate come il Semantic Layer (MetricFlow API). È la scelta per chi preferisce focalizzarsi sulla logica di trasformazione, non sull'infrastruttura.
Data build tool, in altre parole, unisce il lavoro di analisi a quello di ingegneria. Permette di trasformare i dati usando SQL direttamente sul cloud, così da fornire informazioni pulite e standardizzate a chiunque debba usarle.


