Chapter Analytical Data Modeling menutup dengan satu janji: tabel analitik TokoKita sebaiknya hidup sebagai berkas SQL yang dikelola dbt, bukan sebagai skrip tersebar yang sulit dilacak. Chapter ini menepati janji tersebut. dbt (data build tool) adalah framework transformasi open-source yang mengubah kumpulan berkas SELECT menjadi tabel dan view terkelola di warehouse, lengkap dengan dependensi antar model, pengujian data, dan dokumentasi. Kita mulai dari pemasangan, menyusun konfigurasi proyek, mendeklarasikan sumber data, lalu memahami alur eksekusi yang mengubah berkas SQL menjadi tabel.

Apa itu dbt #

dbt mengisi huruf T dalam ELT. Data sudah lebih dulu dimuat mentah ke warehouse — pekerjaan section Pengumpulan dan Ingestion Data — dan dbt melakukan transformasi di dalam warehouse yang sama. Satu model dbt adalah satu berkas .sql berisi satu pernyataan SELECT plus konfigurasi; dari kumpulan berkas tersebut dbt mengompilasi SQL, menyusun urutan eksekusi, lalu membuat tabel atau view di warehouse. dbt hadir dalam dua rupa: dbt Core sebagai CLI open-source yang dipakai section ini, dan dbt Cloud sebagai platform terkelola dengan scheduler serta antarmuka web — keduanya membaca proyek yang sama. Pengantar lengkapnya ada di dokumentasi resmi dbt .

dbt terhubung ke warehouse lewat adapter. Paket dbt-core berisi CLI-nya, dan satu paket adapter menentukan warehouse tujuan: dbt-duckdb untuk DuckDB, dbt-postgres untuk PostgreSQL, dbt-snowflake untuk Snowflake, atau dbt-bigquery untuk BigQuery. Langkah pemasangan mengikuti panduan instalasi dbt :

bash
pip install dbt-core dbt-duckdb
dbt --version

Setelah terpasang, perintah dbt init tokokita_analytics menyiapkan kerangka proyek: direktori models/, berkas dbt_project.yml, dan satu profil koneksi.

profiles.yml: dbt Menyambung ke Warehouse #

dbt memisahkan kode dari koneksi. Nama database, kredensial, dan target environment disimpan di berkas profiles.yml di luar repositori agar kredensial tidak ikut ter-commit; dbt mencocokkan profil dengan proyek lewat nama yang sama:

yaml
tokokita_analytics:
  target: dev
  outputs:
    dev:
      type: duckdb
      path: tokokita.duckdb

Profil di atas mengarahkan proyek tokokita_analytics ke berkas DuckDB lokal tokokita.duckdb pada target dev. Perintah dbt debug menguji koneksi tersebut; bila lulus, proyek siap menerima model pertama.

dbt_project.yml sebagai Pusat Konfigurasi #

Konfigurasi tingkat proyek hidup di dbt_project.yml. Berkas berikut adalah versi TokoKita untuk seluruh section ini:

yaml
name: tokokita_analytics
version: "1.0.0"
config-version: 2

model-paths: ["models"]
snapshot-paths: ["snapshots"]

models:
  tokokita_analytics:
    staging:
      +materialized: view
    marts:
      +materialized: table

Mari kita telaah baris-baris berkas di atas:

  1. Baris 1 (name): nama proyek — harus sama dengan key profil di profiles.yml.
  2. Baris 2-3 (version, config-version): versi proyek kita sendiri, dan versi skema konfigurasi dbt yang dipakai (saat ini 2).
  3. Baris 5-6 (model-paths, snapshot-paths): direktori tempat dbt mencari berkas model SQL dan deklarasi snapshot.
  4. Baris 8-13 (models): konfigurasi per folder. Awalan + membuat pengaturan berlaku untuk semua model di folder tersebut — model di models/staging/ diwujudkan sebagai view, model di models/marts/ sebagai table.

dbt tidak terpasang di lingkungan ini, jadi kita periksa struktur berkas dengan yaml.safe_load — parser yang sama yang dbt pakai untuk membaca konfigurasi YAML:

python
"""Validasi YAML konfigurasi proyek dbt bab 2 (dbt_project.yml + sources.yml)."""
import yaml
from pathlib import Path

BASE = Path(__file__).parent

for nama in ["ch2_dbt_project.yml", "ch2_sources.yml"]:
    path = BASE / nama
    data = yaml.safe_load(path.read_text(encoding="utf-8"))
    print(f"=== {nama} -> valid ===")
    print(yaml.safe_dump(data, sort_keys=False, allow_unicode=True).strip())
    print()

Output yang Dihasilkan:

text
=== ch2_dbt_project.yml -> valid ===
name: tokokita_analytics
version: 1.0.0
config-version: 2
model-paths:
- models
snapshot-paths:
- snapshots
models:
  tokokita_analytics:
    staging:
      +materialized: view
    marts:
      +materialized: table

=== ch2_sources.yml -> valid ===
version: 2
sources:
- name: aplikasi_toko
  schema: raw
  description: Tabel mentah dari aplikasi TokoKita di schema raw
  tables:
  - name: pesanan
  - name: pelanggan

Kedua berkas lolos parsing dan seluruh strukturnya terurai — tidak ada indentasi salah maupun peta yang gagal dibaca parser.

Mendeklarasikan Sumber dengan sources.yml #

Data mentah bukan milik dbt: tabel raw dimuat oleh pipeline ingestion, bukan dibangun oleh model. Karena itu model tidak menuliskan nama tabel mentah secara langsung, melainkan membaca deklarasi source — berkas properties di bawah model-paths:

yaml
version: 2

sources:
  - name: aplikasi_toko
    schema: raw
    description: "Tabel mentah dari aplikasi TokoKita di schema raw"
    tables:
      - name: pesanan
      - name: pelanggan

Deklarasi ini memetakan nama logis aplikasi_toko ke schema raw beserta dua tabelnya. Manfaatnya ada tiga: bila schema raw berganti nama, kita mengubah satu baris di satu berkas; dbt source freshness bisa mengukur kebaruan tiap tabel sumber; dan lineage dari sumber sampai mart terdokumentasi otomatis.

Model dan ref() Membentuk DAG #

Berkas model pertama kita ternyata hanya berupa SELECT biasa. Satu-satunya hal baru adalah fungsi {{ source() }} — Jinja yang dbt ganti menjadi nama tabel lengkap raw.pesanan saat kompilasi:

sql
-- models/staging/stg_pesanan.sql
select
    ord_id      as id_pesanan,
    cust_email  as email,
    ord_status  as status,
    qty,
    unit_price  as harga_satuan
from {{ source('aplikasi_toko', 'pesanan') }}

Model lain memanggil model ini lewat {{ ref('stg_pesanan') }}, dan dari pasangan fungsi source() serta ref() inilah dbt menyusun seluruh dependensi proyek menjadi DAG (directed acyclic graph):

Saat dbt run dijalankan, dbt mengompilasi seluruh model, membaca graf dependensi tersebut, lalu mengeksekusi model demi model mengikuti urutan topologi: stg_pesanan dan stg_pelanggan lebih dulu, fct_pesanan terakhir. Bila satu model gagal, model di hilirannya di-skip — kegagalan tidak menular ke cabang DAG yang tidak bergantung pada model tersebut.

Perintah Eksekusi yang Sering Dipakai #

PerintahPeran
dbt runmembangun semua model sesuai urutan DAG
dbt testmenjalankan data test pada model yang sudah dibangun
dbt snapshotmerekam riwayat sumber (Chapter Snapshots)
dbt buildrun, test, dan snapshot dalam satu perintah sesuai DAG
dbt source freshnessmemeriksa kebaruan tabel sumber
dbt docs generatemembangun situs dokumentasi dari proyek

Daftar lengkap perintah beserta bendanya ada di referensi perintah dbt . Konfigurasi terpasang, sumber terdeklarasi, dan alur eksekusi jelas — satu pertanyaan tersisa: begitu model bertambah dari tiga menjadi tiga puluh, bagaimana kita menatanya agar tetap terpelihara? Jawabannya adalah pengelompokan layer, materi Chapter Model Staging, Intermediate, dan Marts.