Alat Bangun Data atau kesamaan antara Gudang Data dan Smoothie


Apa prinsip-prinsip Gudang Data yang ideal?

Fokus pada nilai bisnis dan analitik tanpa adanya kode boilerplate. Mengelola DWH sebagai basis kode: versi, ulasan, pengujian otomatis, dan CI. Modularitas, ekstensibilitas, sumber terbuka, dan komunitas. Dokumentasi pengguna yang ramah dan visualisasi ketergantungan (Silsilah Data).

Lebih lanjut tentang semua ini dan tentang peran DBT dalam ekosistem Big Data & Analytics - selamat datang di cat.

Halo semuanya


Berhubungan dengan Artemy Kozyr. Selama lebih dari 5 tahun saya telah bekerja dengan gudang data, membangun ETL / ELT, serta analitik dan visualisasi data. Saat ini saya bekerja di Wheely , mengajar di OTUS pada kursus Data Engineer , dan hari ini saya ingin berbagi dengan Anda sebuah artikel yang saya tulis pada malam dimulainya pendaftaran kursus baru .

Ulasan singkat


Kerangka kerja DBT adalah semua tentang huruf T dalam akronim ELT (Extract - Transform - Load).

Dengan munculnya basis data analitik yang produktif dan dapat diukur seperti BigQuery, Redshift, Snowflake, akal apa pun untuk membuat transformasi di luar Gudang Data menghilang. 

DBT tidak mengunduh data dari sumber, tetapi memberikan peluang luar biasa untuk bekerja dengan data yang sudah dimuat ke dalam Penyimpanan (di Penyimpanan Internal atau Eksternal).


Tujuan utama DBT adalah untuk mengambil kode, mengkompilasinya dalam SQL, menjalankan perintah dalam urutan yang benar dalam Repositori.

Struktur proyek DBT


Proyek ini terdiri dari direktori dan file hanya 2 jenis:

  • Model (.sql) - unit transformasi yang dinyatakan oleh kueri SELECT
  • File konfigurasi (.yml) - parameter, pengaturan, tes, dokumentasi

Pada tingkat dasar, pekerjaan disusun sebagai berikut:

  • Pengguna menyiapkan kode model dalam IDE yang praktis
  • Menggunakan CLI, model diluncurkan, DBT mengkompilasi kode model dalam SQL
  • Kode SQL yang dikompilasi dieksekusi di Gudang di urutan yang ditentukan (grafik)

Seperti apa bentuk peluncuran dari CLI:


Semuanya SELECT


Ini adalah fitur pembunuh dari kerangka Alat Data Build. Dengan kata lain, DBT mengabstraksi semua kode yang terkait dengan pematerialisasi kueri Anda di Gudang (variasi dari perintah CREATE, INSERT, UPDATE, DELETE ALTER, GRANT, ...)).

Setiap model melibatkan penulisan satu query SELECT, yang mendefinisikan set data yang dihasilkan.

Pada saat yang sama, logika transformasi dapat bertingkat dan menggabungkan data dari beberapa model lain. Contoh model yang akan membuat showcase pesanan (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

Hal menarik apa yang bisa kita lihat di sini?

Pertama: CTE (Common Table Expressions) digunakan untuk mengatur dan memahami kode yang berisi banyak transformasi dan logika

bisnis.Kedua: Kode model adalah campuran dari SQL dan bahasa Jinja (bahasa templating).

Dalam contoh, loop for digunakan untuk membentuk jumlah untuk setiap metode pembayaran yang ditentukan dalam ekspresi set . Fungsi ref juga digunakan - kemampuan untuk merujuk di dalam kode ke model lain:

  • Pada waktu kompilasi, ref akan dikonversi ke target pointer ke tabel atau tampilan di Repositori
  • ref memungkinkan Anda untuk membuat grafik dependensi model

Adalah Jinja yang menambahkan kemungkinan hampir tak terbatas ke DBT. Yang paling umum digunakan:

  • If / else statement - pernyataan percabangan
  • Untuk loop - loop
  • Variabel - Variabel
  • Makro - Buat Makro

Terwujudnya: Table, View, Incremental


Strategi Materialisasi - suatu pendekatan yang dengannya set data model yang dihasilkan akan disimpan dalam Repositori.

Dalam pertimbangan dasar, ini adalah:

  • Tabel - tabel fisik dalam Storage
  • Lihat - lihat, tabel virtual dalam Repositori

Ada strategi materialisasi yang lebih kompleks:

  • Penambahan - penambahan bertahap (tabel fakta besar); baris baru ditambahkan, yang dimodifikasi diperbarui, yang dihapus dihapus 
  • Ephemeral - model tidak terwujud secara langsung, tetapi berpartisipasi sebagai CTE dalam model lain
  • Strategi lain yang bisa Anda tambahkan sendiri

Selain strategi materialisasi, peluang terbuka untuk optimisasi untuk Gudang tertentu, misalnya:

  • Kepingan salju : Tabel transien, Perilaku gabungan, Pengelompokan tabel, Hibah penyalinan, Pandangan aman
  • Redshift : Distkey, Sortkey (disisipkan, gabungan), Late Binding Views
  • BigQuery : Partisi & pengelompokan tabel, Perilaku gabung, Enkripsi KMS, Label & Tag
  • Spark : Format file (parket, csv, json, orc, delta), partition_by, clustered_by, bucket, incremental_strategy

Repositori berikut saat ini didukung:

  • Postgres
  • Pergeseran merah
  • Bigquery
  • Kepingan salju
  • Presto (sebagian)
  • Spark (sebagian)
  • Microsoft SQL Server (adaptor komunitas)

Mari kita tingkatkan model kita:

  • Jadikan pengisiannya tambahan (Incremental)
  • Tambahkan segmentasi dan urutkan tombol untuk 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

Grafik Ketergantungan Model


Dia adalah pohon ketergantungan. Dia adalah DAG (Sutradara Acyclic Graph - Directional Acyclic Graph).

DBT membuat grafik berdasarkan konfigurasi semua model proyek, atau lebih tepatnya tautan ref () di dalam model ke model lain. Memiliki grafik memungkinkan Anda melakukan hal-hal berikut:

  • Menjalankan model dalam urutan yang benar
  • Paralelisasi window dressing
  • Menjalankan subgraph sembarang 

Contoh visualisasi grafik:


Setiap simpul grafik adalah model, tepi grafik diberikan oleh ekspresi ref.

Kualitas dan Dokumentasi Data


Selain pembentukan model itu sendiri, DBT memungkinkan Anda untuk menguji sejumlah pernyataan tentang kumpulan data yang dihasilkan, seperti:

  • Bukan nol
  • Unik
  • Referensi Integritas - integritas referensi (misalnya, customer_id di tabel pesanan sesuai dengan id di tabel pelanggan)
  • Daftar Valid yang Cocok

Anda dapat menambahkan tes Anda sendiri (tes data khusus), seperti, misalnya,% penyimpangan pendapatan dengan indikator sehari, seminggu, sebulan lalu. Asumsi apa pun yang dirumuskan sebagai kueri SQL bisa menjadi ujian.

Dengan cara ini, penyimpangan yang tidak diinginkan dan kesalahan dalam data dapat ditangkap di etalase Penyimpanan.

Dalam hal dokumentasi, DBT menyediakan mekanisme untuk menambah, membuat versi, dan mendistribusikan metadata dan komentar di tingkat model dan bahkan atribut. 

Berikut ini adalah cara menambahkan tes dan dokumentasi pada tingkat file konfigurasi:

 - 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']

Dan inilah bagaimana dokumentasi ini sudah terlihat di situs web yang dihasilkan:


Makro dan Modul


Tujuan DBT bukanlah untuk menjadi satu set skrip SQL, tetapi untuk menyediakan pengguna dengan alat yang kuat dan kaya fitur untuk membangun transformasi mereka sendiri dan mendistribusikan modul-modul ini.

Makro adalah kumpulan konstruk dan ekspresi yang dapat disebut sebagai fungsi dalam model. Macro memungkinkan Anda untuk menggunakan kembali SQL antara model dan proyek sesuai dengan prinsip rekayasa KERING (Jangan Ulangi Sendiri).

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

Dan penggunaannya:

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

DBT dilengkapi dengan manajer paket yang memungkinkan pengguna untuk menerbitkan dan menggunakan kembali modul dan makro individual.

Ini berarti kemampuan untuk mengunduh dan menggunakan perpustakaan seperti:

  • dbt_utils : bekerja dengan Tanggal / Waktu, Kunci Pengganti, tes Skema, Pivot / Unpivot dan lainnya
  • Templat showcase siap pakai untuk layanan seperti Bajak Salju dan Stripe 
  • Perpustakaan untuk Gudang Data tertentu, seperti Redshift 
  • Logging - Modul Penebangan DBT

Daftar lengkap paket tersedia di hub dbt .

Bahkan lebih banyak fitur


Di sini saya akan menjelaskan beberapa fitur menarik dan implementasi yang saya dan tim gunakan untuk membangun Gudang Data di Wheely .

Pemisahan lingkungan runtime DEV - TEST - PROD


Bahkan dalam cluster DWH yang sama (dalam skema yang berbeda). Misalnya, menggunakan ekspresi berikut:

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

Kode ini secara harfiah mengatakan: untuk dev, tes, lingkungan ci, ambil data hanya untuk 3 hari terakhir dan tidak lebih. Artinya, berjalan di lingkungan ini akan jauh lebih cepat dan membutuhkan lebih sedikit sumber daya. Ketika diluncurkan pada lingkungan prod , kondisi filter akan diabaikan.

Materialisasi penyandian kolom alternatif


Redshift adalah DBMS kolom yang memungkinkan Anda menentukan algoritma kompresi data untuk setiap kolom individu. Pilihan algoritma optimal dapat mengurangi ruang disk yang ditempati 20-50%.

Makro redshift.compress_table akan menjalankan perintah ANALYZE COMPRESSION, membuat tabel baru dengan algoritma pengkodean kolom yang disarankan ditunjukkan oleh kunci segmentasi (dist_key) dan urutkan (key_key), transfer data ke sana, dan hapus salinan lama jika perlu.

Tanda Tangan Makro:

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

Peluncuran Model Logging


Untuk setiap eksekusi model, Anda dapat menggantung kait yang akan dieksekusi sebelum diluncurkan atau segera setelah pembuatan model:

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

Modul logging akan memungkinkan Anda untuk merekam semua metadata yang diperlukan dalam tabel terpisah, yang dengannya Anda selanjutnya dapat mengaudit dan menganalisis area masalah (bottlenecks).

Inilah yang terlihat seperti dasbor pada data pencarian di Looker:


Otomasi Penyimpanan


Jika Anda menggunakan ekstensi fungsionalitas dari Penyimpanan yang digunakan, seperti UDF (Fungsi yang Ditentukan Pengguna), maka versi fungsi-fungsi ini, kontrol akses, dan secara otomatis meluncurkan rilis baru sangat nyaman untuk diterapkan di DBT.

Kami menggunakan UDF dalam Python untuk menghitung nilai hash, domain domain mail, dan mendekode bitmask.

Contoh makro yang membuat UDF pada setiap runtime (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 %}

Di Wheely, kami menggunakan Amazon Redshift, yang didasarkan pada PostgreSQL. Untuk Redshift, penting untuk secara berkala mengumpulkan statistik di atas meja dan membebaskan ruang disk - perintah ANALYZE dan VACUUM.

Untuk melakukan ini, perintah dari redshift_maintenance macro dieksekusi setiap malam:

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


Dimungkinkan untuk menggunakan DBT sebagai layanan (Layanan Terkelola). Dalam satu set:

  • Web IDE untuk mengembangkan proyek dan model
  • Konfigurasi pekerjaan dan pengaturan jadwal
  • Akses sederhana dan nyaman ke log
  • Situs web dengan dokumentasi proyek Anda
  • Koneksi CI (Integrasi Berkelanjutan)


Kesimpulan


Memasak dan mengonsumsi DWH sama menyenangkan dan bermanfaatnya dengan minum smoothie. DBT terdiri dari Jinja, ekstensi khusus (modul), kompiler, engine (pelaksana) dan manajer paket. Setelah mengumpulkan elemen-elemen ini bersama-sama, Anda mendapatkan lingkungan kerja yang lengkap untuk Gudang Data Anda. Hampir tidak ada cara yang lebih baik untuk mengelola transformasi dalam DWH saat ini.



Keyakinan yang diikuti oleh pengembang DBT dirumuskan sebagai berikut:

  • Kode, bukan GUI, adalah abstraksi terbaik untuk mengekspresikan logika analitik yang kompleks
  • Bekerja dengan data harus mengadaptasi praktik terbaik pengembangan perangkat lunak (Rekayasa Perangkat Lunak)

  • Infrastruktur data penting harus dikontrol oleh komunitas pengguna sebagai perangkat lunak sumber terbuka
  • Bukan hanya alat analitik, tetapi kode akan semakin menjadi bagian dari komunitas Open Source.

Keyakinan inti ini telah melahirkan produk yang digunakan hari ini oleh lebih dari 850 perusahaan, dan mereka membentuk dasar dari banyak ekstensi menarik yang akan dibuat di masa depan.

Bagi mereka yang tertarik, ada video pelajaran terbuka yang saya habiskan beberapa bulan lalu sebagai bagian dari pelajaran terbuka di OTUS - Alat Bangun Data untuk repositori Amazon Redshift .

Selain DBT dan Gudang Data, sebagai bagian dari kursus Insinyur Data pada platform OTUS, kolega saya dan saya mengadakan kelas pada sejumlah topik relevan dan modern lainnya:

  • Konsep Arsitektur untuk Aplikasi Big Data
  • Berlatih dengan Spark dan Spark Streaming
  • Metode dan alat pembelajaran untuk memuat sumber data
  • Bangunan menampilkan analitik di DWH
  • NoSQL: HBase, Cassandra, ElasticSearch
  •  
  • :

:


  1. DBT documentation β€” Introduction β€”
  2. What, exactly, is dbt? β€” DBT 
  3. Data Build Tool Amazon Redshift β€” YouTube, OTUS
  4. Greenplum β€” 15 2020
  5. Data Engineering β€” OTUS
  6. Building a Mature Analytics Workflow β€”
  7. It’s time for open source analytics β€” Open Source
  8. Continuous Integration and Automated Build Testing with dbtCloud β€” CI DBT
  9. Getting started with DBT tutorial β€” ,
  10. Jaffle shop β€” Github DBT Tutorial β€” Github,




.



All Articles