- Crear un proyecto de dbt y configurar el adaptador de ClickHouse.
- Definir un modelo.
- Actualizar un modelo.
- Crear un modelo incremental.
- Crear un modelo snapshot.
- Usar vistas materializadas.
Configuración
Preparar ClickHouse
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.s3 para leer los datos de origen desde endpoints públicos e insertarlos. Ejecuta los siguientes comandos para rellenar las tablas:
Conexión a ClickHouse
-
Cree un proyecto de dbt. En este caso, le damos el nombre de nuestra source
imdb. Cuando se le solicite, seleccioneclickhousecomo origen de la base de datos. -
Entre en la carpeta de su proyecto con
cd: - 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:
-
Actualice su archivo
dbt_project.ymlpara especificar nuestro primer modelo,actor_summary, y establezca el profile enclickhouse_imdb. -
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í. -
Desde el directorio IMDB, ejecute el comando
dbt debugpara confirmar si dbt puede conectarse a ClickHouse.Confirme que la respuesta incluyaConnection test: [OK connection ok], lo que indica que la conexión se ha realizado correctamente.
Crear una materialización de vista simple
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.
-
En la carpeta
imdb, elimine el directoriomodels/example: -
Cree un archivo nuevo en
actorsdentro de la carpetamodels. Aquí creamos archivos, cada uno de los cuales representa un modelo de actores: -
Crea los archivos
schema.ymlyactor_summary.sqlen la carpetamodels/actors.El archivoschema.ymldefine nuestras tablas. Posteriormente, estas estarán disponibles para usarse en macros. Editmodels/actors/schema.ymlpara que contenga lo siguiente:actors_summary.sqldefine 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 archivoschema.ymlmediante la funciónsource; por ejemplo,source('imdb', 'movies')se refiere a la tablamoviesde la base de datosimdb. Editemodels/actors/actors_summary.sqlpara que contenga lo siguiente:Fíjate en cómo incluimos la columnaupdated_aten nuestro actor_summary final. Más adelante la usamos para las materializaciones incrementales. -
Desde el directorio
imdb, ejecuta el comandodbt run. -
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 profileclickhouse_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
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.
-
Modifica el archivo
actors_summary.sqlpara que el parámetromaterializedse establezca entable. Observa cómo se defineORDER BYy que usamos el motor de tablaMergeTree: -
Desde el directorio
imdb, ejecuta el comandodbt run. Esta ejecución puede tardar un poco más en completarse: alrededor de 10 s en la mayoría de los equipos. -
Confirma la creación de la tabla
imdb_dbt.actor_summary:Deberías ver la tabla con los tipos de datos adecuados: -
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
-
Primero, modificamos nuestro modelo para que sea incremental. Este cambio requiere:
- 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
idde 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í. - 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ónwhere 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.
actor_summary.sqlde la siguiente manera:Ten en cuenta que nuestro modelo solo responderá a las actualizaciones y adiciones en las tablasrolesyactors. 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í. - 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
-
Ejecuta
dbt runy confirma los resultados de la tabla generada: -
Ahora vamos a agregar datos a nuestro modelo para ilustrar una actualización incremental. Añade el actor “Clicky McClickHouse” a la tabla
actors: -
Hagamos que “Clicky” protagonice 910 películas al azar:
-
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:
-
Ejecuta un
dbt runy confirma que nuestro modelo se haya actualizado y coincida con los resultados anteriores:
Aspectos internos
- El adaptador crea una tabla temporal
actor_sumary__dbt_tmp. Las filas que han cambiado se envían a esta tabla. - 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. - Los resultados de la tabla temporal se envían a la nueva tabla
actor_summary: - 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.
Estrategia append (modo de solo inserciones)
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'.
-
Configura el modo append-only en actor_summary.sql:
-
Añadamos otro actor famoso: Danny DeBito
-
Hagamos que Danny aparezca en 920 películas aleatorias.
-
Ejecuta
dbt runy confirma que Danny se añadió a la tabla actor-summary
imdb_dbt.actor_summary y no se crea ninguna tabla.
Modo de eliminación e inserción (experimental)
incremental_strategy, es decir.
- El adaptador crea una tabla temporal
actor_sumary__dbt_tmp. Las filas que han cambiado se envían a esta tabla. - Se ejecuta un
DELETEen la tabla actualactor_summary. Las filas se eliminan por id a partir deactor_sumary__dbt_tmp - Las filas de
actor_sumary__dbt_tmpse insertan enactor_summarymediante unINSERT INTO actor_summary SELECT * FROM actor_sumary__dbt_tmp.
modo insert_overwrite (experimental)
- Crea una tabla de staging (temporal) con la misma estructura que la relación del modelo incremental:
CREATE TABLE {staging} AS {target}. - Inserta solo los registros nuevos (producidos por SELECT) en la tabla de staging.
- 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
actor_summary.sql no establezca inserts_only=True. Tu models/actor_summary.sql debería verse así:
-
Cree un archivo
actor_summaryen el directoriosnapshots. -
Actualice el contenido del archivo actor_summary.sql con lo siguiente:
- La consulta
selectdefine 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
timestamppara 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 untimestamppara 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).
-
Ejecuta el comando
dbt snapshot.
-
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.
-
Haz que nuestro actor favorito, Clicky McClickHouse, aparezca en otras 10 películas.
-
Vuelve a ejecutar el comando
dbt rundesde el directorioimdb. Esto actualizará el modelo incremental. Una vez completado, ejecutadbt snapshotpara capturar los cambios. -
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.
Uso de seeds
-
Generamos una lista de códigos de género a partir de nuestro conjunto de datos existente. Desde el directorio de dbt, use
clickhouse-clientpara crear el archivoseeds/genre_codes.csv: -
Ejecute el comando
dbt seed. Esto creará una nueva tablagenre_codesen nuestra base de datosimdb_dbt(como se define en la configuración del esquema) con las filas de nuestro archivo CSV. -
Confirme que se hayan cargado: