Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies
Vilka principer bygger det perfekta datalagret pÄ?

Fokus pÄ affÀrsvÀrde och analys utan boilerplate-kod. Hantering av DWH som en kodbas: versionering, granskning, automatiserad testning och CI. Modularitet, skalbarhet, öppen kÀllkod och gemenskap. AnvÀndarvÀnlig dokumentation och visualisering av beroenden (Data Lineage).

Mer om allt detta och DBT:s roll i ekosystemet för Big Data & Analytics — vĂ€lkommen under kĂ„pan.

Hej alla

Artemiy Kozyr hÀr. Jag har arbetat med datalager i över 5 Är, jobbat med byggen av ETL/ELT, samt dataanalys och visualisering. Jag Àr för nÀrvarande verksam pÄ Wheely, undervisar pÄ OTUS i kursen Data Engineer, och idag vill jag dela med mig av en artikel som jag skrev inför starten av ett nytt urval för kursen.

Kort översikt

DBT-ramverket handlar om bokstaven T i akronymen ELT (Extract — Transform — Load).

Med framvÀxten av kraftfulla och skalbara analytiska databaser som BigQuery, Redshift, Snowflake, har det förlorat sin mening att utföra transformationer utanför datalagret. 

DBT laddar inte ner data frÄn kÀllor, men ger enorma möjligheter att arbeta med de data som redan laddats in i lagret (i Internal eller External Storage).

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies
DBT:s huvudsakliga syfte Àr att ta koden, kompilera den till SQL och köra kommandona i rÀtt ordning i lagret.

Strukturen för DBT-projektet

Projektet bestÄr av tvÄ typer av kataloger och filer:

  • Modell (.sql) — en transformationsenhet uttryckt som en SELECT-frĂ„ga
  • Konfigurationsfil (.yml) — parametrar, instĂ€llningar, tester, dokumentation

PÄ grundlÀggande nivÄ byggs arbetet upp pÄ följande sÀtt:

  • AnvĂ€ndaren förbereder kodmodeller i valfri bekvĂ€m IDE
  • Modellerna startas med hjĂ€lp av CLI, DBT kompilerar kodmodellerna till SQL
  • Den kompilera SQL-koden körs i lagret i angiven sekvens (graf)

SÄ hÀr kan en start se ut frÄn CLI:

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

Allt Àr SELECT

Det hÀr Àr en killer-funktion i Data Build Tool-ramverket. Med andra ord, DBT abstraherar all kod relaterad till materialisering av dina frÄgor i lagret (varianter av kommandona CREATE, INSERT, UPDATE, DELETE ALTER, GRANT, 
).

Varje modell innebÀr att skriva en SELECT-frÄga som definierar det resulterande datasaet.

Samtidigt kan logiken för transformationerna vara flervÄnings och konsolidera data frÄn flera andra modeller. Ett exempel pÄ en modell som bygger en bestÀllningsvisning (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

Vad intressant kan vi se hÀr?

För det första: CTE:er (Common Table Expressions) anvÀnds - för att organisera och förstÄ koden, som innehÄller mÄnga transformationer och affÀrslogik

För det andra: Modellkoden Àr en blandning av SQL och Jinja (mallsprÄk).

I exemplet anvĂ€nds en slinga for för att berĂ€kna summan för varje betalningsmetod som anges i uttrycket set. Dessutom anvĂ€nds funktionen ref — en möjlighet att referera inom koden till andra modeller:

  • Vid kompilering ref kommer det att omvandlas till en riktad pekare mot tabellen eller vyerna i lagret
  • ref möjliggör att bygga en graf av beroenden för modeller

Det Àr just Jinja som ger DBT nÀstan obegrÀnsade möjligheter. De mest anvÀnda av dem Àr:

  • If / else-satser - grenkoder
  • For-loopar - loopar
  • Variabler - variabler
  • Makro - skapa makron

Materialisering: Table, View, Incremental

Materialiseringsstrategi - en metod dÀr den resulterande datamÀngden frÄn modellen kommer att sparas i lagret.

Ett grundlÀggande sÀtt att se pÄ detta Àr:

  • Table - en fysisk tabell i lagret
  • View - en vy, en virtuell tabell i lagret

Det finns ocksÄ mer komplexa materialiseringsstrategier:

  • Incremental - inkrementell inlĂ€sning (av stora faktatabeller); nya rader lĂ€ggs till, Ă€ndrade uppdateras, borttagna tas bort 
  • Ephemeral - modellen materialiseras inte direkt, men deltar som CTE i andra modeller
  • Andra strategier som du kan lĂ€gga till sjĂ€lv

Utöver materialiseringsstrategier öppnas möjligheter för optimering för specifika lagringssystem, till exempel:

  • Snowflake: Transient tables, Merge behavior, Table clustering, Copying grants, Secure views
  • Redshift: Distkey, Sortkey (interleaved, compound), Late Binding Views
  • BigQuery: Table partitioning & clustering, Merge behavior, KMS Encryption, Labels & Tags
  • Spark: Filformat (parquet, csv, json, orc, delta), partition_by, clustered_by, buckets, incremental_strategy

För nÀrvarande stöds följande lagringslösningar:

  • Postgres
  • Redshift
  • BigQuery
  • Snowflake
  • Presto (delvis)
  • Spark (delvis)
  • Microsoft SQL Server (community-adapter)

LÄt oss förbÀttra vÄr modell:

  • Gör dess innehĂ„ll inkrementellt (Incremental)
  • LĂ€gg till segmenterings- och sorteringsnycklar för Redshift

-- Modellkonfiguration:
-- Inkrementellt innehÄll, unik nyckel för uppdatering av poster (unique_key)
-- Segmenteringsnyckel (dist), sorteringsnyckel (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() -%}
       -- Denna filter kommer att tillÀmpas endast för inkrementell körning
       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

Modellernas beroendegraf

Det kallas Ă€ven beroendetrĂ€d. Det Ă€r ocksĂ„ en DAG (Directed Acyclic Graph — Riktad Acyklisk Graf).

DBT bygger grafen baserat pÄ konfigurationen av alla projektmodeller, mer specifikt referenserna ref() inom modellerna till andra modeller. Att ha en graf möjliggör följande:

  • Körning av modeller i korrekt sekvens
  • Parallellisering av skapande av datalager
  • Körning av en godtycklig undergraf 

Ett exempel pÄ grafvisualisering:

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies
Varje nod i grafen Àr en modell, kanterna i grafen bestÀms av uttrycket ref.

Datakvalitet och Dokumentation

Förutom att skapa sjÀlva modellerna, lÄter DBT oss testa en rad antaganden (assertions) om den resulterande datamÀngden, sÄsom:

  • Not Null
  • Unique
  • Referensintegritet — referensintegritet (till exempel, customer_id i tabellen orders motsvarar id i tabellen customers)
  • ÖverensstĂ€mmelse med en lista över tillĂ„tna vĂ€rden

Det gÄr att lÀgga till egna tester (custom data tests), som exempelvis % avvikelse i intÀkterna med siffror frÄn igÄr, förra veckan, eller förra mÄnaden. Varje antagande, formulerat som en SQL-frÄga, kan bli ett test.

PÄ sÄ sÀtt kan oönskade avvikelser och fel i data spÄras i datalager.

NÀr det gÀller dokumentation tillhandahÄller DBT mekanismer för att lÀgga till, versionera och distribuera metadata och kommentarer pÄ modellnivÄ och till och med pÄ attributnivÄ. 

SÄ hÀr ser det ut att lÀgga till tester och dokumentation pÄ konfigurationsfilnivÄ:

 - name: fct_orders
   description: Denna tabell har grundlÀggande information om bestÀllningar, samt nÄgra hÀrledda fakta baserade pÄ betalningar
   columns:
     - name: order_id
       tests:
         - unique # kontroll av unika vÀrden
         - not_null # kontroll av null
       description: Detta Àr en unik identifierare för en bestÀllning
     - name: customer_id
       description: Utlandsskydd till tabellen för kunder
       tests:
         - not_null
         - relationships: # kontroll av referentiell integritet
             to: ref('dim_customers')
             field: customer_id
     - name: order_date
       description: Datum (UTC) dÄ bestÀllningen gjordes
     - name: status
       description: '{{ doc("orders_status") }}'
       tests:
         - accepted_values: # kontroll av giltiga vÀrden
             values: ['placed', 'shipped', 'completed', 'return_pending', 'returned']

SÄ hÀr ser denna dokumentation ut nÀr den redan Àr pÄ den genererade webbplatsen:

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

Makron och Moduler

Syftet med DBT Àr inte sÄ mycket att vara en uppsÀttning SQL-skript, utan att ge anvÀndarna kraftfulla och rika verktyg för att bygga sina egna transformationer och distribuera dessa moduler.

Makron Ă€r en uppsĂ€ttning konstruktioner och uttryck som kan anropas som funktioner inom modeller. Makron gör det möjligt att Ă„teranvĂ€nda SQL mellan modeller och projekt i enlighet med ingenjörsprincipen DRY (Don’t Repeat Yourself).

Exempel pÄ makro:

{% 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 %}

Och dess anvÀndning:

{% set column_name = 'product' %}
select
 product,
 {{ rename_category(column_name) }} -- anrop av makro
from my_table

DBT levereras med en paketchef (packages) som lÄter anvÀndare publicera och ÄteranvÀnda individuella moduler och makron.

Det betyder möjlighet att ladda ner och anvÀnda sÄdana bibliotek som:

  • dbt_utils: arbete med Datum/Tid, Surrogatnycklar, Schema-tester, Pivot/Unpivot och annat
  • FĂ€rdiga mallar för datalager som Snowplow och Stripe 
  • Bibliotek för specifika datalager, till exempel Redshift 
  • Logging — Modul för loggning av DBT:s aktivitet

Den fullstÀndiga listan över paket kan ses pÄ dbt hub.

Ännu fler möjligheter

HÀr beskriver jag nÄgra andra intressanta funktioner och implementeringar som jag och teamet anvÀnder för att bygga ett datalager i Wheely.

Delning av körmiljöer DEV — TEST — PROD

Även inom en och samma DWH-kluster (inom olika scheman). Till exempel med hjĂ€lp av följande uttryck:

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 -%}
  
)

Denna kod sÀger bokstavligen: för miljöerna dev, test, ci ta endast med data frÄn de senaste 3 dagarna och inte mer. Det vill sÀga att körningar i dessa miljöer kommer att gÄ mycket snabbare och krÀva fÀrre resurser. NÀr den körs i miljön prod kommer filtervillkoret att ignoreras.

Materialisering med alternativ kolumnkodning

Redshift Ă€r en kolumnorienterad DBMS som möjliggör att ange komprimeringsalgoritmer för varje enskild kolumn. Valet av optimala algoritmer kan minska den upptagna lagringen med 20–50%.

Makro redshift.compress_table kommer att köra kommandot ANALYZE COMPRESSION, skapa en ny tabell med rekommenderade kolumnkodningsalgoritmer, angivna segmenteringsnycklar (dist_key) och sorteringsnycklar (sort_key), överföra data till den, och om nödvÀndigt ta bort den gamla kopian.

Makrosignatur:

{{ compress_table(schema, table,
                 drop_backup=False,
                 comprows=none|Integer,
                 sort_style=none|compound|interleaved,
                 sort_keys=none|List,
                 dist_style=none|all|even,
                 dist_key=none|String) }}

Loggning av modellkörningar

För varje körning av en modell kan man anhÀnga hooks (hooks) som utförs innan starten eller omedelbart efter avslutningen av modells skapande:

   pre-hook: "{{ logging.log_model_start_event() }}"
   post-hook: "{{ logging.log_model_end_event() }}"

Loggningsmodulen gör det möjligt att registrera all nödvÀndig metadata i en separat tabell, som senare kan anvÀndas för att utföra revision och analys av problemomrÄden (bottlenecks).

SÄ hÀr ser instrumentpanelen ut pÄ loggningsdata i Looker:

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

Automatisering av underhÄll av datalagret

Om du anvÀnder nÄgra funktionalitetsförlÀngningar i det anvÀnda datalagret, sÄsom UDF (User Defined Functions), Àr versionshantering av dessa funktioner, hantering av Ätkomster, och automatiserad utrullning av nya versioner mycket bekvÀmt att genomföra i DBT.

Vi anvÀnder UDF i Python för att berÀkna hash-vÀrden, domÀner av e-postadresser, och avkoda bitmasker (bitmask).

Exempel pÄ ett makro som skapar UDF i vilken körningsmiljö som helst (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 %}

PĂ„ Wheely anvĂ€nder vi Amazon Redshift, som Ă€r baserat pĂ„ PostgreSQL. För Redshift Ă€r det viktigt att regelbundet samla in statistik om tabeller och frigöra diskutrymme — kommandona ANALYZE och VACUUM, respektive.

För detta körs kommandona frÄn makrot redshift_maintenance varje natt:

{% 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 %}

DBT Cloud

Det finns möjlighet att anvÀnda DBT som en tjÀnst (Managed Service). I paketet ingÄr:

  • Web IDE för utveckling av projekt och modeller
  • Konfiguration av jobb och schemalĂ€ggning
  • Enkel och smidig Ă„tkomst till loggar
  • Webbplats med dokumentationen för ditt projekt
  • Anslutning av CI (Continuous Integration)

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

Slutsats

Att förbereda och anvÀnda DWH blir lika trevligt och givande som att dricka smoothies. DBT bestÄr av Jinja, anvÀndardefinierade tillÀgg (moduler), en kompilator, en motor (executor) och en paketförvaltare. Genom att sammanföra dessa element fÄr du en komplett arbetsmiljö för ditt datalager. Det finns knappast idag ett bÀttre sÀtt att hantera transformationer inom DWH.

Data Build Tool eller vad har Data Warehouse gemensamt med Smoothies

De övertygelser som DBT-utvecklarna följde formuleras sÄ hÀr:

  • Kod, inte GUI, Ă€r den bĂ€sta abstraktionen för att uttrycka komplex analytisk logik.
  • Arbete med data bör anpassa de bĂ€sta metoderna inom programvaruutveckling (Software Engineering).

  • Den viktigaste infrastrukturen för databehandling bör kontrolleras av anvĂ€ndarsamhĂ€llet som programvara med öppen kĂ€llkod.
  • Inte bara analytiska verktyg, utan Ă€ven kod kommer alltmer att bli en del av Open Source-gemenskapen.

Dessa grundlÀggande övertygelser har skapat en produkt som idag anvÀnds av mer Àn 850 företag, och de utgör grunden för mÄnga intressanta utvidgningar som kommer att skapas i framtiden.

För de som Ă€r intresserade finns det en videoinspelning av en öppen lektion som jag höll för nĂ„gra mĂ„nader sedan som en del av en öppen lektion pĂ„ OTUS — Data Build Tool för Amazon Redshift-lagring..

Förutom DBT och datalagerdÀck, hÄller jag och mina kollegor förelÀsningar om en rad andra aktuella och moderna Àmnen inom Data Engineer-kursen pÄ OTUS:

  • Arkitekturella koncept för Big Data-applikationer.
  • Praktik med Spark och Spark Streaming.
  • Att lĂ€ra sig sĂ€tt och verktyg för att ladda datakĂ€llor.
  • Bygga analytiska visningar i DWH.
  • NoSQL-koncept: HBase, Cassandra, ElasticSearch.
  • Principer för organisering av övervakning och orkestrering. 
  • Slutprojekt: sammanfoga alla fĂ€rdigheter med mentorsupport.

LĂ€nkar:

  1. DBT-dokumentation — Introduktion. — Officiell dokumentation.
  2. Vad Ă€r egentligen dbt? — Översikt av en av författarna till DBT. 
  3. Data Build Tool för Amazon Redshift-lagring. — YouTube, inspelning av öppen lektion OTUS.
  4. Introduktion till Greenplum. — NĂ€sta öppna lektion den 15 maj 2020.
  5. Kurs i Data Engineering. — OTUS.
  6. Byggande av en mogen analysarbetsflöde. — En blick mot framtiden för databehandling och analys.
  7. Det Ă€r dags för öppen kĂ€llkod-analys. — Utvecklingen av analys och pĂ„verkan av Open Source.
  8. Kontinuerlig integration och automatiserad byggtestning med dbtCloud. — Principer för att bygga CI med DBT.
  9. Komma igĂ„ng med DBT-handledning. — Praktik, steg-för-steg-instruktioner för sjĂ€lvstĂ€ndigt arbete.
  10. Jaffle shop — Github DBT-handledning — Github, kod för utbildningsprojekt

Mer om kursen.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster