Data Build Tool atau persamaan antara Data Warehouse dan Smoothie
Berdasarkan prinsip apa Gudang Data yang ideal dibangun?
Fokus pada nilai bisnis dan analitik tanpa adanya kode boilerplate. Mengelola DWH sebagai basis kode: pembuatan versi, peninjauan, pengujian otomatis, dan CI. Modular, dapat diperluas, sumber terbuka, dan komunitas. Dokumentasi yang mudah digunakan 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
Artemy Kozyr menghubungi kami. Selama lebih dari 5 tahun saya telah bekerja dengan gudang data, membangun ETL/ELT, serta analisis dan visualisasi data. Saat ini saya sedang bekerja di Wheely, saya mengajar di OTUS pada suatu kursus Insinyur Data, dan hari ini saya ingin berbagi dengan Anda sebuah artikel yang saya tulis sebagai antisipasi permulaan pendaftaran baru untuk kursus tersebut.
Ulasan singkat
Kerangka kerja DBT adalah tentang T dalam akronim ELT (Extract - Transform - Load).
Dengan munculnya database analitik yang produktif dan skalabel seperti BigQuery, Redshift, Snowflake, tidak ada gunanya melakukan transformasi di luar Data Warehouse.
DBT tidak mengunduh data dari sumber, tetapi memberikan peluang besar untuk bekerja dengan data yang sudah dimuat ke dalam Penyimpanan (di Penyimpanan Internal atau Eksternal).
Tujuan utama DBT adalah untuk mengambil kode, mengkompilasinya menjadi SQL, menjalankan perintah dalam urutan yang benar di Repositori.
Struktur Proyek DBT
Proyek ini hanya terdiri dari 2 jenis direktori dan file:
Model (.sql) - unit transformasi yang diekspresikan oleh kueri SELECT
Pada tingkat dasar, pekerjaan disusun sebagai berikut:
Pengguna menyiapkan kode model dalam IDE apa pun yang nyaman
Menggunakan CLI, model diluncurkan, DBT mengkompilasi kode model ke dalam SQL
Kode SQL yang dikompilasi dieksekusi di Penyimpanan dalam urutan tertentu (grafik)
Berikut tampilan berjalan dari CLI:
Semuanya PILIH
Ini adalah fitur mematikan dari kerangka Data Build Tool. Dengan kata lain, DBT mengabstraksi semua kode yang terkait dengan perwujudan kueri Anda ke dalam Store (variasi dari perintah CREATE, INSERT, UPDATE, DELETE ALTER, GRANT, ...).
Model apa pun melibatkan penulisan satu kueri SELECT yang mendefinisikan kumpulan data yang dihasilkan.
Dalam hal ini, logika transformasi dapat bersifat multi-level dan mengkonsolidasikan data dari beberapa model lainnya. Contoh model yang akan membuat etalase 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 saja yang bisa kita lihat di sini?
Pertama: Menggunakan CTE (Common Table Expressions) - untuk mengatur dan memahami kode yang mengandung banyak transformasi dan logika bisnis
Kedua: Kode model adalah campuran SQL dan bahasa Jinja (bahasa templat).
Contohnya menggunakan loop untuk untuk menghasilkan jumlah untuk setiap metode pembayaran yang ditentukan dalam ekspresi set. Fungsi tersebut juga digunakan ref β kemampuan untuk mereferensikan model lain dalam kode:
Selama kompilasi ref akan dikonversi menjadi penunjuk target ke tabel atau tampilan di Penyimpanan
ref memungkinkan Anda membuat grafik ketergantungan model
Persis Jinja menambahkan kemungkinan yang hampir tak terbatas pada DBT. Yang paling umum digunakan adalah:
Pernyataan if/else - pernyataan cabang
Untuk loop
Variabel
Makro - membuat makro
Perwujudan: Tabel, Tampilan, Inkremental
Strategi materialisasi adalah pendekatan yang dengannya kumpulan data model yang dihasilkan akan disimpan di Penyimpanan.
Secara mendasar itu adalah:
Tabel - tabel fisik di Penyimpanan
Lihat - lihat, tabel virtual di Penyimpanan
Ada juga strategi materialisasi yang lebih kompleks:
Inkremental - pemuatan tambahan (tabel fakta besar); baris baru ditambahkan, baris yang diubah diperbarui, baris yang dihapus dihapus
Ephemeral - model tidak terwujud secara langsung, namun berpartisipasi sebagai CTE dalam model lainnya
Strategi lain apa pun yang dapat Anda tambahkan sendiri
Selain strategi materialisasi, terdapat peluang pengoptimalan untuk Penyimpanan tertentu, misalnya:
Mari kita buat pengisiannya bertambah bertahap (Inkremental)
Mari tambahkan kunci segmentasi dan pengurutan 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
Ini juga merupakan pohon ketergantungan. Ia juga dikenal sebagai DAG (Grafik Asiklik Terarah).
DBT membuat grafik berdasarkan konfigurasi semua model proyek, atau lebih tepatnya, tautan ref() dalam model ke model lain. Memiliki grafik memungkinkan Anda melakukan hal-hal berikut:
Menjalankan model dalam urutan yang benar
Paralelisasi pembentukan etalase
Menjalankan subgraf sewenang-wenang
Contoh visualisasi grafik:
Setiap simpul dari grafik adalah model; tepi grafik ditentukan oleh ekspresi ref.
Kualitas dan Dokumentasi Data
Selain menghasilkan model itu sendiri, DBT memungkinkan Anda menguji sejumlah asumsi tentang kumpulan data yang dihasilkan, seperti:
Bukan Nol
Khas Papua
Integritas Referensi - integritas referensial (misalnya, id_pelanggan di tabel pesanan sesuai dengan id di tabel pelanggan)
Mencocokkan daftar nilai yang dapat diterima
Dimungkinkan untuk menambahkan pengujian Anda sendiri (pengujian data khusus), seperti, misalnya, % deviasi pendapatan dengan indikator dari hari, minggu, bulan lalu. Asumsi apa pun yang dirumuskan sebagai kueri SQL bisa menjadi ujian.
Dengan cara ini, Anda dapat menangkap penyimpangan dan kesalahan yang tidak diinginkan pada data di jendela Gudang.
Dalam hal dokumentasi, DBT menyediakan mekanisme untuk menambahkan, membuat versi, dan mendistribusikan metadata dan komentar pada tingkat model dan bahkan atribut.
Berikut tampilan penambahan 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 tampilan dokumentasi di situs web yang dihasilkan:
Makro dan Modul
Tujuan DBT bukan untuk menjadi sekumpulan skrip SQL, namun untuk menyediakan sarana yang kuat dan kaya fitur kepada pengguna untuk membangun transformasi mereka sendiri dan mendistribusikan modul-modul ini.
Makro adalah kumpulan konstruksi dan ekspresi yang dapat disebut sebagai fungsi dalam model. Makro memungkinkan Anda menggunakan kembali SQL antara model dan proyek sesuai dengan prinsip teknik KERING (Jangan Ulangi Diri 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 dapat memuat dan menggunakan perpustakaan seperti:
dbt_utils: bekerja dengan Tanggal/Waktu, Kunci Pengganti, tes Skema, Pivot/Unpivot, dan lainnya
Templat etalase siap pakai untuk layanan seperti Bajak salju ΠΈ Garis
Perpustakaan untuk Penyimpanan Data tertentu, mis. Redshift
Di sini saya akan menjelaskan beberapa fitur dan implementasi menarik lainnya yang saya dan tim gunakan untuk membangun Gudang Data Wheely.
Pemisahan lingkungan runtime DEV - TEST - PROD
Bahkan dalam klaster DWH yang sama (dalam skema yang berbeda). Misalnya saja 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 lingkungan dev, tes, 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. Saat berjalan di lingkungan melecut kondisi filter akan diabaikan.
Perwujudan dengan pengkodean kolom alternatif
Redshift adalah DBMS kolom yang memungkinkan Anda mengatur algoritma kompresi data untuk setiap kolom. Memilih algoritma yang optimal dapat mengurangi ruang disk sebesar 20-50%.
Makro redshift.compress_table akan menjalankan perintah ANALYZE COMPRESSION, membuat tabel baru dengan algoritma pengkodean kolom yang direkomendasikan, kunci segmentasi yang ditentukan (dist_key) dan kunci pengurutan (sort_key), mentransfer data ke dalamnya, dan, jika perlu, menghapus salinan lama.
Modul logging akan memungkinkan Anda untuk mencatat semua metadata yang diperlukan dalam tabel terpisah, yang selanjutnya dapat digunakan untuk mengaudit dan menganalisis kemacetan.
Berikut tampilan dashboard berdasarkan data logging di Looker:
Otomatisasi Pemeliharaan Penyimpanan
Jika Anda menggunakan beberapa ekstensi fungsionalitas Repositori yang digunakan, seperti UDF (Fungsi Buatan Pengguna), maka pembuatan versi fungsi-fungsi ini, kontrol akses, dan peluncuran rilis baru secara otomatis sangat mudah dilakukan di DBT.
Kami menggunakan UDF dengan Python untuk menghitung hash, domain email, dan decoding bitmask.
Contoh makro yang membuat UDF di lingkungan eksekusi apa pun (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 mengumpulkan statistik tabel secara teratur dan mengosongkan ruang disk - masing-masing perintah ANALYZE dan VACUUM.
Untuk melakukan ini, perintah dari makro redshift_maintenance dijalankan 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 %}
Awan DBT
Dimungkinkan untuk menggunakan DBT sebagai layanan (Layanan Terkelola). Termasuk:
Web IDE untuk mengembangkan proyek dan model
Konfigurasi dan penjadwalan pekerjaan
Akses sederhana dan nyaman ke log
Situs web dengan dokumentasi proyek Anda
Menghubungkan CI (Integrasi Berkelanjutan)
Kesimpulan
Mempersiapkan dan mengonsumsi DWH menjadi menyenangkan dan bermanfaat seperti meminum smoothie. DBT terdiri dari Jinja, ekstensi pengguna (modul), kompiler, pelaksana, dan manajer paket. Dengan menyatukan elemen-elemen ini, 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 dianut oleh para pengembang DBT dirumuskan sebagai berikut:
Kode, bukan GUI, adalah abstraksi terbaik untuk mengekspresikan logika analitis yang kompleks
Bekerja dengan data harus mengadaptasi praktik terbaik dalam rekayasa perangkat lunak (Rekayasa Perangkat Lunak)
Infrastruktur data penting harus dikendalikan oleh komunitas pengguna sebagai perangkat lunak sumber terbuka
Tidak hanya alat analitik, tetapi juga kode akan semakin menjadi milik komunitas Open Source
Keyakinan inti ini telah melahirkan produk yang digunakan oleh lebih dari 850 perusahaan saat ini, dan menjadi dasar dari banyak perluasan menarik yang akan diciptakan di masa depan.
Selain DBT dan Pergudangan Data, sebagai bagian dari kursus Insinyur Data di platform OTUS, saya dan kolega saya mengajar kelas tentang sejumlah topik lain yang relevan dan modern:
Konsep Arsitektur untuk Aplikasi Big Data
Berlatih dengan Spark dan Spark Streaming
Menjelajahi metode dan alat untuk memuat sumber data
Membangun pameran analitis di DWH
Konsep NoSQL: HBase, Cassandra, ElasticSearch
Prinsip pemantauan dan orkestrasi
Tugas Akhir: menggabungkan semua keterampilan di bawah dukungan pendampingan