Los desarrolladores de DBT se han propuesto lanzar una nueva release importante cada cuatro meses y, por el momento, lo están cumpliendo. El pasado mes de octubre, se lanzó y se ha ido corrigiendo la versión 1.9 de este popular framework. En ella, encontramos algunas mejoras interesantes que vamos a analizar a continuación.
El changelog completo de la versión puede consultarse en Github, donde encontraremos pormenorizado tanto los cambios pequeños “fixes” como las nuevas “features”.
Principales novedades de DBT 1.9
Nuevo método de selección llamado “unit_test:”
Se ha incluido la capacidad de agregar un nuevo método de selección llamado unit_test:
para que los usuarios puedan filtrar y ejecutar exclusivamente pruebas unitarias en DBT de forma más sencilla. Al implementarlo, los comandos dbt list
y dbt test
deberían reconocer y seleccionar solo estos nodos de prueba unitaria.
Parámetro host en “dbt docs server”
Se añade una funcionalidad para permitir a los desarrolladores especificar una dirección de enlace diferente para el comando dbt docs serve
, que actualmente se enlaza a 127.0.0.1 por defecto debido a la vulnerabilidad. Esta ha sido una petición bastante solicitada en la comunidad, ya que al configurar 127.0.0.1 como predeterminada, algunos usuarios tenían problemas con sus despliegues porque no podían cambiar fácilmente esta dirección. Esta nueva feature busca añadir la opción para que sea posible especificar manualmente una dirección de enlace alternativa usando un nuevo parámetro --host
en el comando.
Hooks en “TestTasks”
Ahora, tanto las pruebas unitarias como las pruebas de datos pueden ejecutarse con configuraciones específicas de adaptador, como seleccionar un warehouse personalizado en Snowflake antes de comenzar la prueba. Esto es posible gracias a la incorporación de «hooks» pre y post test, que permiten ajustar el entorno de manera automática según lo que cada prueba requiera. Anteriormente, esta feature estaba disponible solo al ejecutar modelos, pero la comunidad ya puede configurar sus pruebas para que se adapten al warehouse y recursos específicos necesarios, brindando mayor control y personalización en sus flujos de trabajo de prueba.
Nombre dinámico para los Snapshots
Los snapshots podrán generar automáticamente los nombres de esquema y base de datos creados dinámicamente, sin necesidad de especificar manualmente target_schema
o target_database
.
Hasta esta versión, los snapshots requerían que se estableciera explícitamente esta información. Esto resultaba un poco engorroso y limitaba bastante la flexibilidad al trabajar en entornos como desarrollo, pruebas y producción. Con esta mejora, si no se especifican los valores de target_schema
o target_database
, DBT utilizará por defecto los macros generate_schema_name
y generate_database_name
, igual que en otros recursos como los modelos y las seeds.
Time spines
Esta funcionalidad facilita el soporte para granularidades sub-diarias, manteniendo la eficiencia en las consultas. Con ella, podremos definir una columna de granularidad estándar standard_granularity_column
y añadir columnas personalizadas de granularidad custom_granularities_columns
con diferentes niveles. La idea es que DBT pueda usar la granularidad más compatible para optimizar el rendimiento en cada consulta.
Con esta configuración, la comunidad podrá definir tiempos complejos y personalizados directamente en sus modelos mediante YAML, por ejemplo:
models:
- name: my_time_spine
description: "my favorite time spine"
time_spine:
standard_granularity_column: date_day # column for the standard grain of your table
custom_granularities_columns: # additional custom granularities for your timespine
- name: fiscal_year
offset: 2
- name: my_other_column
offset: 3
columns:
- name: date_day
granularity: day # set granularity at column-level for standard_granularity_column
Configuración campos Snapshot
La nueva versión facilita la personalización de los nombres de los campos meta generados en snapshots, como dbt_valid_from
y dbt_valid_to
. Hasta el momento, si querías cambiar el nombre a estas columnas, tenías que hacerlo en un paso posterior del pipeline. Ahora, los usuarios pueden especificar sus propios nombres directamente en la configuración del snapshot, simplificando así la gestión de estos campos sin necesidad de crear una vista adicional.
Un ejemplo sería:
{{
config(
target_database='analytics',
target_schema='snapshots',
unique_key='id',
strategy='timestamp',
updated_at='updated_at',
snapshot_meta_column_names={
dbt_valid_from: grace_valid_from,
dbt_valid_to: grace_valid_to
}
)
}}
Control de “Fallo elegante” en pre-ejecuciones
Ahora, podemos usar hooks de pre-ejecución (on-run-start
) como chequeos preliminares de manera más efectiva. En esta actualización, un hook de on-run-start
fallará de forma controlada y deteniendo la ejecución de nodos en el DAG si una validación falla, sin detener la ejecución de DBT de forma abrupta ni bloquear la creación del informe run_results.json.
Snapshot en YAML
Actualmente, para la definición de un Snapshot debemos de generar un archivo con una proyección y añadir una configuración Jinja. Se propone añadir soporte para YAML para la definición de un Snapshot. Aunque es posible que en la mayoría de casos agilizaría la definición, no está del todo claro si se pierde flexibilidad dentro de la proyección.
Un ejemplo de definición sería:
snapshots:
- name: orders_snapshot
relation: source('jaffle_shop', 'orders')
config:
schema: snapshots
database: analytics
unique_key: id
strategy: timestamp
updated_at: updated_at
La verdad es que se está discutiendo bastante al respecto. En mi opinión, no tiene mucho sentido que los snapshot queden apartados totalmente de los modelos, ya que parecen un modelo pero con una materialización diferente. Podría ser un nuevo modelo de materialización que tenga efectos solamente en el motor de DBT.
Microbatch incremental
He dejado esta feature para el final y, la verdad, he estudiado la release principalmente por esta nueva característica que ya se venía anunciando desde la versión 1.7.
En esta versión, se introduce la estrategia microbatch incremental, que mejora el rendimiento de los modelos incrementales procesando los datos en lotes más pequeños. En lugar de procesar grandes volúmenes en un solo lote, ahora se pueden definir varias columnas de partición, lo que reduce los cuellos de botella y mejora la eficiencia en el procesamiento de datos. Además, esta función permitiría el reprocesado de los lotes fallidos, de manera que no tendríamos que volver a generar toda la query en caso de que hubiera un fallo por cualquier problema en tiempo de ejecución.
Veamos cómo funciona el sistema de microbatch. Este sistema se enmarca dentro de las materializaciones incrementales. Básicamente, la materialización está diseñada para actualizar de manera eficiente las tablas de su almacén de datos transformando y cargando únicamente datos nuevos o modificados desde la última ejecución. En lugar de volver a procesar un conjunto de datos completo cada vez, los modelos incrementales procesan una cantidad menor de filas y luego agregan, actualizan o reemplazan esas filas en la tabla existente.
Al ejecutar este tipo de modelos, ya sea en la primera ejecución o en actualizaciones incrementales, DBT divide el procesamiento en varios lotes o consultas totalmente independientes, configurados según los parámetros event_time
y batch_size
.
{{
config(
materialized='incremental',
incremental_strategy='microbatch',
event_time='event_occured_at',
batch_size='day',
lookback=3,
begin='2020-01-01',
full_refresh=false
)
}}
select * from {{ ref('stg_events') }}
Aquí podemos ver un ejemplo de la configuración que consta de 4 argumentos:
event_time
es una marca temporal de cada registro.begin
define la fecha de inicio del primer lote.batch_size
determina la granularidad del lote, es decir, día, mes, etc.lookback
define la cantidad de lotes anteriores a procesar para capturar registros atrasados.
DBT adapta un comando para que podamos lanzar periodos concretos. Esto es muy útil para realizar cargas de periodos históricos que han podido ser modificadas o que necesitan algún tipo de intervención.
Lo que sucede realmente por debajo es que cada batch creará una consulta independiente. Por ejemplo, si se ejecuta el modelo el 1 de octubre, DBT crearía consultas independientes para cada día entre el 28 de septiembre y el 1 de octubre, ambos inclusive (cuatro lotes en total).
La consulta 2024-10-01 se vería así:
select * from (
select * from "analytics"."stg_events"
where my_time_field >= '2024-10-01 00:00:00'
and my_time_field < '2024-10-02 00:00:00'
)
# Según su plataforma de datos, DBT elegirá el mecanismo atómico más eficiente para insertar, actualizar o reemplazar estos cuatro lotes (2024-09-28, 2024-09-29, 2024-09-30 y 2024-10-01) en la tabla existente
Conclusión
La versión 1.9 de DBT introduce mejoras que aumentan la flexibilidad y eficiencia en la gestión de datos y, sobre todo, de pruebas. Además, se refuerza el control sobre el entorno y se hace más sencillo ejecutar tareas complejas con un rendimiento optimizado.
Por último, hemos visto en qué consiste el sistema de microbatches, que será muy útil para tratar grandes cantidades de datos, especialmente en warehouses cloud donde el procesamiento es algo a tener en cuenta.