Saltar al contenido principal
Esta sección proporciona guías para configurar dbt y el adaptador de ClickHouse, así como un ejemplo de uso de dbt con ClickHouse a partir de un conjunto de datos público de IMDB. El ejemplo abarca los siguientes pasos:
  1. Crear un proyecto de dbt y configurar el adaptador de ClickHouse.
  2. Definir un modelo.
  3. Actualizar un modelo.
  4. Crear un modelo incremental.
  5. Crear un modelo snapshot.
  6. Usar vistas materializadas.
Estas guías están pensadas para usarse junto con el resto de la documentación, las características y configuraciones y la referencia de materializaciones.

Configuración

Sigue las instrucciones de la sección Configuración de dbt y el adaptador de ClickHouse para preparar tu entorno. Importante: Lo siguiente se ha probado con Python 3.9.

Preparar ClickHouse

dbt destaca al modelar datos con muchas relaciones. A modo de ejemplo, proporcionamos un pequeño conjunto de datos de IMDb con el siguiente esquema relacional. Este conjunto de datos proviene del repositorio de conjuntos de datos relacionales. Aunque es sencillo en comparación con los esquemas habituales que se usan con dbt, representa una muestra manejable: Usamos un subconjunto de estas tablas, como se muestra. Cree las siguientes tablas:
La columna created_at de la tabla roles, cuyo valor predeterminado es now(). La usamos más adelante para identificar actualizaciones incrementales en nuestros modelos; consulta Modelos incrementales.
Usamos la función s3 para leer los datos de origen desde endpoints públicos e insertarlos. Ejecuta los siguientes comandos para rellenar las tablas:
La ejecución de estos pasos puede variar en función de tu ancho de banda, pero cada uno debería tardar solo unos segundos en completarse. Ejecuta la siguiente consulta para obtener un resumen de cada actor, ordenado por número de apariciones en películas de mayor a menor, y confirmar que los datos se hayan cargado correctamente:
La respuesta debería verse así:
En las guías siguientes, convertiremos esta consulta en un modelo, materializándolo en ClickHouse como una vista y una tabla de dbt.

Conexión a ClickHouse

  1. Cree un proyecto de dbt. En este caso, le damos el nombre de nuestra source imdb. Cuando se le solicite, seleccione clickhouse como origen de la base de datos.
  2. Entre en la carpeta de su proyecto con cd:
  3. En este punto, necesitará el editor de texto que prefiera. En los ejemplos siguientes, usamos el popular VS Code. Al abrir el directorio IMDB, debería ver un conjunto de archivos yml y sql:
  4. Actualice su archivo dbt_project.yml para especificar nuestro primer modelo, actor_summary, y establezca el profile en clickhouse_imdb.
  5. A continuación, debemos proporcionar a dbt los connection details de nuestra instancia de ClickHouse. Añada lo siguiente a ~/.dbt/profiles.yml:
    Tenga en cuenta que debe modificar el usuario y la contraseña. Hay más opciones de configuración documentadas aquí.
  6. Desde el directorio IMDB, ejecute el comando dbt debug para confirmar si dbt puede conectarse a ClickHouse.
    Confirme que la respuesta incluya Connection test: [OK connection ok], lo que indica que la conexión se ha realizado correctamente.

Crear una materialización de vista simple

Cuando se usa la materialización de vista, un modelo se vuelve a crear como una vista en cada ejecución mediante una instrucción CREATE VIEW AS en ClickHouse. Esto no requiere almacenamiento adicional de datos, pero las consultas serán más lentas que con las materializaciones de tabla.
  1. En la carpeta imdb, elimine el directorio models/example:
  2. Cree un archivo nuevo en actors dentro de la carpeta models. Aquí creamos archivos, cada uno de los cuales representa un modelo de actores:
  3. Crea los archivos schema.yml y actor_summary.sql en la carpeta models/actors.
    El archivo schema.yml define nuestras tablas. Posteriormente, estas estarán disponibles para usarse en macros. Edit models/actors/schema.yml para que contenga lo siguiente:
    actors_summary.sql define nuestro modelo propiamente dicho. Tenga en cuenta que, en la función config, también indicamos que el modelo se materialice como una vista en ClickHouse. Nuestras tablas se referencian desde el archivo schema.yml mediante la función source; por ejemplo, source('imdb', 'movies') se refiere a la tabla movies de la base de datos imdb. Edite models/actors/actors_summary.sql para que contenga lo siguiente:
    Fíjate en cómo incluimos la columna updated_at en nuestro actor_summary final. Más adelante la usamos para las materializaciones incrementales.
  4. Desde el directorio imdb, ejecuta el comando dbt run.
  5. dbt representará el model como una vista en ClickHouse, tal como se solicitó. Ahora podemos consultar esta vista directamente. Esta vista se habrá creado en la base de datos imdb_dbt; esto lo determina el parámetro schema en el archivo ~/.dbt/profiles.yml, dentro del profile clickhouse_imdb.
    Al consultar esta vista, podemos reproducir los resultados de nuestra consulta anterior con una sintaxis más sencilla:

Crear una materialización como tabla

En el ejemplo anterior, nuestro modelo se materializó como una vista. Aunque esto puede ofrecer un rendimiento suficiente para algunas consultas, los SELECT más complejos o las consultas que se ejecutan con frecuencia pueden materializarse mejor como una tabla. Esta materialización resulta útil para los modelos que serán consultados por herramientas de BI, ya que garantiza una experiencia más ágil para los usuarios. En la práctica, esto hace que los resultados de la consulta se almacenen en una nueva tabla, con la sobrecarga de almacenamiento asociada; en efecto, se ejecuta un INSERT TO SELECT. Ten en cuenta que esta tabla se reconstruirá cada vez; es decir, no es incremental. Por lo tanto, los conjuntos de resultados grandes pueden dar lugar a tiempos de ejecución prolongados; consulta dbt Limitations.
  1. Modifica el archivo actors_summary.sql para que el parámetro materialized se establezca en table. Observa cómo se define ORDER BY y que usamos el motor de tabla MergeTree:
  2. Desde el directorio imdb, ejecuta el comando dbt run. Esta ejecución puede tardar un poco más en completarse: alrededor de 10 s en la mayoría de los equipos.
  3. Confirma la creación de la tabla imdb_dbt.actor_summary:
    Deberías ver la tabla con los tipos de datos adecuados:
  4. Confirma que los resultados de esta tabla sean coherentes con las respuestas anteriores. Observa una mejora apreciable en el tiempo de respuesta ahora que el modelo es una tabla:
    No dudes en ejecutar otras consultas sobre este modelo. Por ejemplo, ¿qué actores tienen las películas mejor valoradas con más de 5 apariciones?

Creación de una materialización incremental

El ejemplo anterior creó una tabla para materializar el modelo. Esta tabla se reconstruirá en cada ejecución de dbt. Esto puede resultar inviable y extremadamente costoso para conjuntos de resultados grandes o transformaciones complejas. Para abordar este problema y reducir el tiempo de construcción, dbt ofrece materializaciones incrementales. Esto permite a dbt insertar o actualizar registros en una tabla desde la última ejecución, por lo que resulta adecuado para datos de tipo evento. Internamente, se crea una tabla temporal con todos los registros actualizados y, a continuación, tanto los registros no modificados como los actualizados se insertan en una nueva tabla de destino. Esto conlleva limitaciones similares para conjuntos de resultados grandes a las del modelo de tabla. Para superar estas limitaciones en conjuntos grandes, el adaptador admite el modo ‘inserts_only’, en el que todas las actualizaciones se insertan en la tabla de destino sin crear una tabla temporal (más información a continuación). Para ilustrar este ejemplo, añadiremos al actor “Clicky McClickHouse”, que aparecerá en la friolera de 910 películas, lo que garantiza que haya aparecido en más filmes incluso que Mel Blanc.
  1. Primero, modificamos nuestro modelo para que sea incremental. Este cambio requiere:
    1. unique_key - Para garantizar que el adaptador pueda identificar de forma unívoca las filas, debemos proporcionar una unique_key; en este caso, el campo id de nuestra consulta será suficiente. Esto garantiza que no tendremos filas duplicadas en nuestra tabla materializada. Para obtener más información sobre las restricciones de unicidad, consulta aquí.
    2. Filtro incremental - También debemos indicarle a dbt cómo identificar qué filas han cambiado en una ejecución incremental. Esto se consigue proporcionando una expresión delta. Normalmente, esto implica un timestamp para los datos de eventos; de ahí nuestro campo de timestamp updated_at. Esta columna, cuyo valor predeterminado es now() cuando se insertan filas, permite identificar nuevos roles. Además, necesitamos contemplar el caso alternativo en el que se agregan nuevos actores. Usando la variable {{this}} para denotar la tabla materializada existente, obtenemos la expresión where id > (select max(id) from {{ this }}) or updated_at > (select max(updated_at) from {{this}}). La incrustamos dentro de la condición {% if is_incremental() %}, lo que garantiza que solo se use en ejecuciones incrementales y no cuando la tabla se construye por primera vez. Para obtener más información sobre cómo filtrar filas en modelos incrementales, consulta este apartado de la documentación de dbt.
    Actualiza el archivo actor_summary.sql de la siguiente manera:
    Ten en cuenta que nuestro modelo solo responderá a las actualizaciones y adiciones en las tablas roles y actors. Para responder a todas las tablas, se recomienda a los usuarios dividir este modelo en varios submodelos, cada uno con sus propios criterios incrementales. A su vez, estos modelos pueden referenciarse y conectarse entre sí. Para obtener más información sobre las referencias cruzadas entre modelos, consulta aquí.
  2. Ejecuta dbt run y confirma los resultados de la tabla generada:
  3. Ahora vamos a agregar datos a nuestro modelo para ilustrar una actualización incremental. Añade el actor “Clicky McClickHouse” a la tabla actors:
  4. Hagamos que “Clicky” protagonice 910 películas al azar:
  5. Confirma que ahora sí es el actor con más apariciones consultando directamente la tabla de origen subyacente, sin pasar por ningún modelo de dbt:
  6. Ejecuta un dbt run y confirma que nuestro modelo se haya actualizado y coincida con los resultados anteriores:

Aspectos internos

Podemos identificar las sentencias ejecutadas para realizar la actualización incremental anterior consultando el registro de consultas de ClickHouse.
Ajuste la consulta anterior al período de ejecución. Dejamos al usuario la inspección de los resultados, pero destacamos la estrategia general que utiliza el adaptador para realizar actualizaciones incrementales:
  1. El adaptador crea una tabla temporal actor_sumary__dbt_tmp. Las filas que han cambiado se envían a esta tabla.
  2. Se crea una nueva tabla, actor_summary_new,. A continuación, las filas de la tabla anterior se envían de la antigua a la nueva, con una comprobación para asegurarse de que los identificadores de fila no existan en la tabla temporal. Esto resuelve eficazmente las actualizaciones y los duplicados.
  3. Los resultados de la tabla temporal se envían a la nueva tabla actor_summary:
  4. Por último, la nueva tabla se intercambia de forma atómica con la versión anterior mediante una instrucción EXCHANGE TABLES. A su vez, se eliminan la tabla anterior y la temporal.
Esto se muestra a continuación: Esta estrategia puede presentar dificultades en modelos muy grandes. Para obtener más información, consulte Limitaciones.

Estrategia append (modo de solo inserciones)

Para superar las limitaciones de los conjuntos de datos grandes en los modelos incrementales, el adaptador usa el parámetro de configuración de dbt incremental_strategy. Este puede establecerse con el valor append. Cuando se configura así, las filas actualizadas se insertan directamente en la tabla de destino (también conocida como imdb_dbt.actor_summary) y no se crea ninguna tabla temporal. Nota: El modo append-only requiere que tus datos sean inmutables o que los duplicados sean aceptables. Si quieres un modelo de tabla incremental que admita filas modificadas, ¡no uses este modo! Para ilustrar este modo, agregaremos otro actor nuevo y volveremos a ejecutar dbt run con incremental_strategy='append'.
  1. Configura el modo append-only en actor_summary.sql:
  2. Añadamos otro actor famoso: Danny DeBito
  3. Hagamos que Danny aparezca en 920 películas aleatorias.
  4. Ejecuta dbt run y confirma que Danny se añadió a la tabla actor-summary
Observa lo mucho más rápida que fue esa ejecución incremental en comparación con la inserción de “Clicky”. Si vuelves a revisar la tabla query_log, verás las diferencias entre las 2 ejecuciones incrementales:
En esta ejecución, solo se añaden directamente las filas nuevas a la tabla imdb_dbt.actor_summary y no se crea ninguna tabla.

Modo de eliminación e inserción (experimental)

Históricamente, ClickHouse solo ha ofrecido un soporte limitado para las actualizaciones y eliminaciones, en forma de mutaciones. Estas pueden consumir muchísimas operaciones de E/S y, por lo general, conviene evitarlas. ClickHouse 22.8 introdujo las eliminaciones ligeras y ClickHouse 25.7 introdujo las actualizaciones ligeras. Con la introducción de estas funciones, los cambios realizados mediante consultas de actualización individuales, incluso cuando se materializan de forma asíncrona, se reflejan al instante desde la perspectiva del usuario. Este modo puede configurarse para un modelo mediante el parámetro incremental_strategy, es decir.
Esta estrategia opera directamente sobre la tabla del modelo de destino, por lo que, si se produce algún problema durante la operación, es probable que los datos del modelo incremental queden en un estado no válido; no hay actualización atómica. En resumen, este enfoque:
  1. El adaptador crea una tabla temporal actor_sumary__dbt_tmp. Las filas que han cambiado se envían a esta tabla.
  2. Se ejecuta un DELETE en la tabla actual actor_summary. Las filas se eliminan por id a partir de actor_sumary__dbt_tmp
  3. Las filas de actor_sumary__dbt_tmp se insertan en actor_summary mediante un INSERT INTO actor_summary SELECT * FROM actor_sumary__dbt_tmp.
Este proceso se muestra a continuación:

modo insert_overwrite (experimental)

Realiza los siguientes pasos:
  1. Crea una tabla de staging (temporal) con la misma estructura que la relación del modelo incremental: CREATE TABLE {staging} AS {target}.
  2. Inserta solo los registros nuevos (producidos por SELECT) en la tabla de staging.
  3. Reemplaza solo las particiones nuevas (presentes en la tabla de staging) en la tabla de destino.

Este enfoque tiene las siguientes ventajas:
  • Es más rápido que la estrategia predeterminada porque no copia toda la tabla.
  • Es más seguro que otras estrategias porque no modifica la tabla original hasta que la operación INSERT se completa correctamente: en caso de fallo intermedio, la tabla original no se modifica.
  • Implementa la práctica recomendada en ingeniería de datos de la “inmutabilidad de las particiones”, lo que simplifica el procesamiento de datos incremental y en paralelo, los rollbacks, etc.

Crear un snapshot

Los snapshots de dbt permiten mantener un registro de los cambios en un modelo mutable a lo largo del tiempo. Esto, a su vez, permite realizar consultas en un momento determinado sobre los modelos, de modo que los analistas puedan “retroceder en el tiempo” para ver el estado anterior de un modelo. Esto se logra mediante dimensiones de cambio lento de tipo 2, donde las columnas de fecha de inicio y fin registran cuándo una fila era válida. Esta funcionalidad es compatible con el adaptador de ClickHouse y se muestra a continuación. Este ejemplo asume que has completado Creating an Incremental Table Model. Asegúrate de que tu actor_summary.sql no establezca inserts_only=True. Tu models/actor_summary.sql debería verse así:
  1. Cree un archivo actor_summary en el directorio snapshots.
  2. Actualice el contenido del archivo actor_summary.sql con lo siguiente:
Algunas observaciones sobre este contenido:
  • La consulta select define los resultados de los que desea capturar snapshots a lo largo del tiempo. La función ref se usa para hacer referencia al modelo actor_summary que creamos anteriormente.
  • Necesitamos una columna timestamp para indicar los cambios en los registros. Nuestra columna updated_at (consulte Creación de un modelo de tabla incremental) puede usarse aquí. El parámetro strategy indica que usamos un timestamp para señalar las actualizaciones, mientras que el parámetro updated_at especifica la columna que se debe utilizar. Si esto no está presente en su modelo, también puede usar la estrategia check. Esto es mucho menos eficiente y requiere que el usuario especifique una lista de columnas para comparar. dbt compara los valores actuales e históricos de estas columnas y registra cualquier cambio (o no hace nada si son idénticos).
  1. Ejecuta el comando dbt snapshot.
Observa que se ha creado la tabla actor_summary_snapshot en la base de datos snapshots (determinada por el parámetro target_schema).
  1. Al observar estos datos, verá cómo dbt ha incluido las columnas dbt_valid_from y dbt_valid_to. La última tiene valores nulos. Las ejecuciones posteriores la actualizarán.
  2. Haz que nuestro actor favorito, Clicky McClickHouse, aparezca en otras 10 películas.
  3. Vuelve a ejecutar el comando dbt run desde el directorio imdb. Esto actualizará el modelo incremental. Una vez completado, ejecuta dbt snapshot para capturar los cambios.
  4. Si ahora consultamos nuestra instantánea, observa que tenemos 2 filas para Clicky McClickHouse. Nuestra entrada anterior ahora tiene un valor en dbt_valid_to. El nuevo valor se registra con ese mismo valor en la columna dbt_valid_from y con un valor dbt_valid_to de null. Si hubiera filas nuevas, estas también se añadirían a la instantánea.
Para obtener más información sobre los snapshots de dbt, consulte aquí.

Uso de seeds

dbt permite cargar datos desde archivos CSV. Esta capacidad no es adecuada para cargar exportaciones grandes de una base de datos; está pensada más bien para archivos pequeños que suelen usarse para tablas de códigos y diccionarios, por ejemplo, para asociar códigos de país con nombres de países. Como ejemplo sencillo, generaremos y luego cargaremos una lista de códigos de género mediante la funcionalidad de seed.
  1. Generamos una lista de códigos de género a partir de nuestro conjunto de datos existente. Desde el directorio de dbt, use clickhouse-client para crear el archivo seeds/genre_codes.csv:
  2. Ejecute el comando dbt seed. Esto creará una nueva tabla genre_codes en nuestra base de datos imdb_dbt (como se define en la configuración del esquema) con las filas de nuestro archivo CSV.
  3. Confirme que se hayan cargado:

Más información

Las guías anteriores solo ofrecen una visión general de la funcionalidad de dbt. Se recomienda a los usuarios consultar la excelente documentación de dbt.
Última modificación el 12 de junio de 2026