Data Build Tool o ciò chì hè cumunu trà Data Warehouse è Smoothie
Su quali principii hè custruitu un Data Warehouse ideale?
Focus nantu à u valore cummerciale è l'analisi in l'absenza di codice boilerplate. Gestisce DWH cum'è codice base: versioning, review, testing automatizatu è CI. Modulari, estensibile, open source è cumunità. Documentazione user-friendly è visualizazione di dependenza (Data Lineage).
Più nantu à tuttu questu è nantu à u rolu di DBT in l'ecosistema Big Data & Analytics - benvenutu à cat.
Saluta à tutti
Artemy Kozyr hè in cuntattu. Per più di 5 anni aghju travagliatu cù magazzini di dati, custruendu ETL / ELT, è ancu di analisi di dati è visualizazione. Sò attualmente travagliendu in Wheely, Insegnu à OTUS nantu à un cursu Ingegneria di dati, è oghje vogliu sparte cun voi un articulu chì aghju scrittu in anticipazione di u principiu nova iscrizzione à u corsu.
Revisione corta
U framework DBT hè tutta di a T in l'acronimu ELT (Extract - Transform - Load).
Cù l'avventu di tali basa di dati analitiche produttivi è scalabili cum'è BigQuery, Redshift, Snowflake, ùn ci era nunda di fà trasfurmazioni fora di u Data Warehouse.
DBT ùn scarica micca e dati da e fonti, ma furnisce grandi opportunità per travaglià cù dati chì sò digià stati caricati in u Storage (in Storage Internal o External).
U scopu principale di DBT hè di piglià u codice, compilallu in SQL, eseguisce i cumandamenti in a sequenza curretta in u Repository.
Struttura di Prughjettu DBT
U prughjettu hè custituitu da cartulari è schedarii di solu 2 tipi:
Model (.sql) - una unità di trasfurmazioni espressa da una query SELECT
File di cunfigurazione (.yml) - paràmetri, paràmetri, testi, documentazione
À u livellu di basa, u travagliu hè strutturatu cum'è seguita:
L'utilizatore prepara u codice mudellu in ogni IDE cunvene
Utilizendu a CLI, i mudelli sò lanciati, DBT compila u codice di mudellu in SQL
U codice SQL compilatu hè eseguitu in u Storage in una sequenza data (graficu)
Eccu ciò chì pò esse in esecuzione da a CLI:
Tuttu hè SELECT
Questa hè una funzione assassina di u framework di Data Build Tool. In altre parolle, DBT astrae tuttu u codice assuciatu à materializà e vostre dumande in a Store (variazioni da i cumandamenti CREATE, INSERT, UPDATE, DELETE ALTER, GRANT, ...).
Ogni mudellu implica scrive una dumanda SELECT chì definisce u settore di dati resultanti.
In questu casu, a logica di trasfurmazioni pò esse multi-livellu è cunsulidà dati da parechji altri mudelli. Un esempiu di un mudellu chì custruisce una vitrina di ordine (f_orders):
{% set payment_methods = ['credit_card', 'coupon', 'bank_transfer', 'gift_card'] %}
with orders as (
select * from {{ ref('stg_orders') }}
),
order_payments as (
select * from {{ ref('order_payments') }}
),
final as (
select
orders.order_id,
orders.customer_id,
orders.order_date,
orders.status,
{% for payment_method in payment_methods -%}
order_payments.{{payment_method}}_amount,
{% endfor -%}
order_payments.total_amount as amount
from orders
left join order_payments using (order_id)
)
select * from final
Chì cose interessanti pudemu vede quì?
Prima: Aduprate CTE (Common Table Expressions) - per urganizà è capisce u codice chì cuntene assai trasfurmazioni è logica cummerciale
Siconda: U codice mudellu hè una mistura di SQL è lingua u nomu (lingua di mudellu).
L'esempiu usa un ciclu di per generà a quantità per ogni metudu di pagamentu specificatu in l'espressione ghjocu. A funzione hè ancu usata ref - a capacità di riferimentu à altri mudelli in u codice:
Durante a compilazione ref serà cunvertitu in un punteru di destinazione à una tavola o vista in Storage
ref permette di custruisce un graficu di dependenza di mudellu
Era u nomu aghjunghje pussibulità quasi illimitate à DBT. I più cumunimenti usati sò:
Dichjarazioni If / else - dichjarazioni di ramu
Per i loops
Variabili
Macro - crià macros
Materializazione: Tavola, Vista, Incrementale
A strategia di materializazione hè un approcciu secondu chì u risultatu di dati di u mudellu serà guardatu in u Storage.
In termini basi hè:
Table - tavola fisica in u Storage
Vista - vista, tavola virtuale in Storage
Ci sò ancu strategie di materializazione più cumplesse:
Incrementale - carica incrementale (di grandi tabelle di fatti); novi linee sò aghjunte, e linee cambiate sò aghjurnate, e linee eliminate sò sbulicate
Ephemeral - u mudellu ùn si materializeghja micca direttamente, ma participa cum'è CTE in altri mudelli
Qualchese altre strategie pudete aghjunghje sè stessu
In più di e strategie di materializazione, ci sò opportunità per ottimisazione per Storage specifichi, per esempiu:
fioccu di nevi: Tavule transitori, Cumportamentu di fusione, Raggruppamentu di tavule, Copia di cuncessione, Viste sicure
Redshift: Distkey, Sortkey (interleaved, compostu), Late Binding Views
bigquery: Partitioning & clustering Table, Cumportamentu di Merge, Criptificazione KMS, Etichette è Tags
Spark: Formatu di u schedariu (parquet, csv, json, orc, delta), partition_by, clustered_by, buckets, incremental_strategy
I seguenti Storages sò attualmente supportati:
postgres
Redshift
bigquery
fioccu di nevi
Prestu (parzialmente)
Spark (parzialmente)
Microsoft SQL Server (adattatore di a cumunità)
Migliuremu u nostru mudellu:
Facemu u so riempimentu incrementale (Incremental)
Aghjunghjemu e chjave di segmentazione è di ordinamentu per Redshift
-- Конфигурация модели:
-- Инкрементальное наполнение, уникальный ключ для обновления записей (unique_key)
-- Ключ сегментации (dist), ключ сортировки (sort)
{{
config(
materialized='incremental',
unique_key='order_id',
dist="customer_id",
sort="order_date"
)
}}
{% set payment_methods = ['credit_card', 'coupon', 'bank_transfer', 'gift_card'] %}
with orders as (
select * from {{ ref('stg_orders') }}
where 1=1
{% if is_incremental() -%}
-- Этот фильтр будет применен только для инкрементального запуска
and order_date >= (select max(order_date) from {{ this }})
{%- endif %}
),
order_payments as (
select * from {{ ref('order_payments') }}
),
final as (
select
orders.order_id,
orders.customer_id,
orders.order_date,
orders.status,
{% for payment_method in payment_methods -%}
order_payments.{{payment_method}}_amount,
{% endfor -%}
order_payments.total_amount as amount
from orders
left join order_payments using (order_id)
)
select * from final
Graficu di dependenza di mudellu
Hè ancu un arbre di dependenza. Hè cunnisciutu ancu DAG (Dirittu Acyclic Graph).
DBT custruisce un gràficu basatu nantu à a cunfigurazione di tutti i mudelli di prughjettu, o megliu, ref () ligami in mudelli à altri mudelli. Avè un graficu permette di fà e cose seguenti:
Modelli in esecuzione in a sequenza curretta
Parallelizazione di a furmazione di vetrina
Esecuzione di un subgrafu arbitrariu
Esempiu di visualizazione grafica:
Ogni node di u graficu hè un mudellu; i bordi di u graficu sò specificati da l'espressione ref.
Qualità di Dati è Documentazione
In più di generà i mudelli stessi, DBT permette di pruvà una quantità di ipotesi nantu à u settore di dati resultanti, cum'è:
Micca nulla
Unique
Integrità di riferimentu - integrità referenziale (per esempiu, customer_id in a tavola di ordini currisponde à l'id in a tavola di i clienti)
Cumpagnia di a lista di i valori accettabili
Hè pussibule aghjunghje i vostri testi (testi di dati persunalizati), cum'è, per esempiu, % deviazione di i rivenuti cù indicatori da un ghjornu, una settimana, un mese fà. Ogni ipotesi formulata cum'è una dumanda SQL pò diventà una prova.
In questu modu, pudete catturà deviazioni indesiderate è errori in dati in i Windows Warehouse.
In termini di documentazione, DBT furnisce miccanismi per aghjunghje, versioning, è distribuzione di metadati è cumenti à u mudellu è ancu i livelli di attributi.
Eccu ciò chì l'aghjunzione di testi è documentazioni pare à u livellu di u schedariu di cunfigurazione:
- name: fct_orders
description: This table has basic information about orders, as well as some derived facts based on payments
columns:
- name: order_id
tests:
- unique # проверка на уникальность значений
- not_null # проверка на наличие null
description: This is a unique identifier for an order
- name: customer_id
description: Foreign key to the customers table
tests:
- not_null
- relationships: # проверка ссылочной целостности
to: ref('dim_customers')
field: customer_id
- name: order_date
description: Date (UTC) that the order was placed
- name: status
description: '{{ doc("orders_status") }}'
tests:
- accepted_values: # проверка на допустимые значения
values: ['placed', 'shipped', 'completed', 'return_pending', 'returned']
È quì hè ciò chì sta documentazione pare nantu à u situ web generatu:
Macro è Moduli
U scopu di DBT ùn hè micca tantu di diventà un inseme di script SQL, ma di furnisce l'utilizatori cù un modu putente è riccu di funzioni per custruisce e so propiu trasfurmazioni è distribuzendu questi moduli.
I macros sò insemi di custruzzioni è espressioni chì ponu esse chjamati cum'è funzioni in mudelli. I macros permettenu di riutilizà SQL trà mudelli è prughjetti in cunfurmità cù u principiu di ingegneria DRY (Ùn ripetite micca).
Macro esempiu:
{% macro rename_category(column_name) %}
case
when {{ column_name }} ilike '%osx%' then 'osx'
when {{ column_name }} ilike '%android%' then 'android'
when {{ column_name }} ilike '%ios%' then 'ios'
else 'other'
end as renamed_product
{% endmacro %}
È u so usu:
{% set column_name = 'product' %}
select
product,
{{ rename_category(column_name) }} -- вызов макроса
from my_table
DBT vene cun un gestore di pacchetti chì permette à l'utilizatori di pubblicà è riutilizà moduli individuali è macros.
Questu significa esse capace di carricà è aduprà biblioteche cum'è:
dbt_utils: travaglià cù Data / Ora, Chjave Surrogate, Test di Schema, Pivot / Unpivot è altri
Modelli di vetrina pronti per servizii cum'è Snowplow и Stripe
Biblioteche per Data Stores specifichi, p.e. Redshift
Una lista cumpleta di pacchetti pò esse truvata à hub dbt.
Ancu più funziunalità
Quì descriveraghju uni pochi di altre caratteristiche interessanti è implementazioni chì a squadra è aghju aduprà per custruisce un Data Warehouse in Wheely.
Separazione di ambienti runtime DEV - TEST - PROD
Ancu in u stessu cluster DWH (in schemi differenti). Per esempiu, usendu l'espressione seguente:
with source as (
select * from {{ source('salesforce', 'users') }}
where 1=1
{%- if target.name in ['dev', 'test', 'ci'] -%}
where timestamp >= dateadd(day, -3, current_date)
{%- endif -%}
)
Stu codice dice literalmente: per l'ambienti dev, prova, ci piglià dati solu per l'ultimi 3 ghjorni è micca più. Vale à dì, a corsa in questi ambienti serà assai più veloce è richiede menu risorse. Quandu corre nantu à l'ambiente prod a cundizione di u filtru serà ignorata.
Materializazione cù codificazione di colonna alternativa
Redshift hè un DBMS columnar chì permette di stabilisce algoritmi di cumpressione di dati per ogni colonna individuale. A selezzione di algoritmi ottimali pò riduce u spaziu di discu da 20-50%.
Macro redshift.compress_table eseguirà u cumandimu ANALYSE COMPRESSION, creà una nova tavula cù l'algoritmi di codificazione di colonna cunsigliati, chjavi di segmentazione specificati (dist_key) è chjavi di sorte (sort_key), trasferisce i dati à questu, è, se ne necessariu, sguassate a vechja copia.
U modulu di logging vi permetterà di registrà tutte e metadati necessarii in una tavola separata, chì pò esse aduprata in seguitu per audità è analizà i colli di bottiglia.
Eccu ciò chì pare u dashboard basatu annantu à i dati di logging in Looker:
Automatizazione di u Mantenimentu di u Storage
Se aduprate alcune estensioni di e funziunalità di u Repository utilizatu, cum'è UDF (User Defined Functions), allora a versione di queste funzioni, u cuntrollu di l'accessu è u rolling automatizatu di novi versioni hè assai còmuda per fà in DBT.
Utilizemu UDF in Python per calculà hash, domini di email, è decodificazione di bitmask.
Un esempiu di una macro chì crea un UDF in ogni ambiente di esecutivu (dev, test, prod):
{% macro create_udf() -%}
{% set sql %}
CREATE OR REPLACE FUNCTION {{ target.schema }}.f_sha256(mes "varchar")
RETURNS varchar
LANGUAGE plpythonu
STABLE
AS $$
import hashlib
return hashlib.sha256(mes).hexdigest()
$$
;
{% endset %}
{% set table = run_query(sql) %}
{%- endmacro %}
In Wheely usemu Amazon Redshift, chì hè basatu annantu à PostgreSQL. Per Redshift, hè impurtante di cullà regularmente statistiche nantu à e tavule è liberà u spaziu di discu - i cumandamenti ANALYZE è VACUUM, rispettivamente.
Per fà questu, i cumandamenti da a macro redshift_maintenance sò eseguiti ogni notte:
{% macro redshift_maintenance() %}
{% set vacuumable_tables=run_query(vacuumable_tables_sql) %}
{% for row in vacuumable_tables %}
{% set message_prefix=loop.index ~ " of " ~ loop.length %}
{%- set relation_to_vacuum = adapter.get_relation(
database=row['table_database'],
schema=row['table_schema'],
identifier=row['table_name']
) -%}
{% do run_query("commit") %}
{% if relation_to_vacuum %}
{% set start=modules.datetime.datetime.now() %}
{{ dbt_utils.log_info(message_prefix ~ " Vacuuming " ~ relation_to_vacuum) }}
{% do run_query("VACUUM " ~ relation_to_vacuum ~ " BOOST") %}
{{ dbt_utils.log_info(message_prefix ~ " Analyzing " ~ relation_to_vacuum) }}
{% do run_query("ANALYZE " ~ relation_to_vacuum) %}
{% set end=modules.datetime.datetime.now() %}
{% set total_seconds = (end - start).total_seconds() | round(2) %}
{{ dbt_utils.log_info(message_prefix ~ " Finished " ~ relation_to_vacuum ~ " in " ~ total_seconds ~ "s") }}
{% else %}
{{ dbt_utils.log_info(message_prefix ~ ' Skipping relation "' ~ row.values() | join ('"."') ~ '" as it does not exist') }}
{% endif %}
{% endfor %}
{% endmacro %}
U situ web cù a documentazione di u vostru prughjettu
Cunnessu CI (Integrazione Continua)
cunchiusioni
A preparazione è u cunsumu DWH diventa cusì piacevule è benefica cum'è beie un smoothie. DBT hè custituitu da Jinja, estensioni d'utilizatori (moduli), un compilatore, un esecutore è un gestore di pacchetti. Aghjunghjendu questi elementi, uttene un ambiente di travagliu cumpletu per u vostru Data Warehouse. Ùn ci hè micca un modu megliu per gestisce a trasfurmazioni in DWH oghje.
E credenze seguite da i sviluppatori di DBT sò formulate cusì:
U codice, micca GUI, hè a megliu astrazione per esprime una logica analitica cumplessa
U travagliu cù e dati deve adattà e migliori pratiche in ingegneria di software (Ingegneria di software)
L'infrastruttura di dati critichi deve esse cuntrullata da a cumunità di l'utilizatori cum'è software open source
Micca solu l'arnesi analitici, ma ancu u codice diventeranu sempre più a pruprietà di a cumunità Open Source
Queste credenze core anu generatu un pruduttu chì hè adupratu da più di 850 cumpagnie oghje, è formanu a basa di parechje estensioni eccitanti chì saranu create in u futuru.
In più di DBT è Data Warehousing, cum'è parte di u cursu di Data Engineer nantu à a piattaforma OTUS, i mo culleghi è aghju insegnu classi nantu à una quantità di altri temi pertinenti è muderni:
Cuncepzioni architettoniche per l'applicazioni di Big Data
Pratica cù Spark è Spark Streaming
Esplora metudi è arnesi per caricate fonti di dati
Custruì vitrine analitiche in DWH
NoSQL cuncetti: HBase, Cassandra, ElasticSearch
Principii di monitoraghju è orchestrazione
Prughjettu Finale: mette tutte e cumpetenze inseme sottu supportu di mentoring