dbt di 2026: Transformasi Data, Pengujian, dan Pertanyaan Wawancara
Tutorial dbt untuk data engineer: transformasi SQL, pemodelan berlapis, strategi incremental, pengujian data, serta pertanyaan wawancara teknis dengan contoh kode untuk 2026.

dbt (data build tool) telah menjadi framework standar untuk mentransformasi data di dalam data warehouse modern. Pada tahun 2026, lebih dari 40.000 perusahaan menggunakan dbt dalam produksi. Tutorial ini membahas mekanisme inti transformasi dbt, strategi pengujian, serta pertanyaan-pertanyaan yang sering muncul dalam wawancara data engineering.
dbt menangani huruf T dalam ELT. Framework ini mengompilasi pernyataan SQL SELECT menjadi DDL (CREATE TABLE, CREATE VIEW, MERGE) dan mengeksekusinya terhadap warehouse — Snowflake, BigQuery, Redshift, atau Databricks. Version control, resolusi dependensi, pengujian, dan dokumentasi sudah tersedia secara bawaan.
Pemodelan Berlapis: Staging, Intermediate, dan Marts
Proyek dbt yang terstruktur dengan baik memisahkan transformasi menjadi tiga lapisan. Pendekatan ini, yang dipopulerkan oleh komunitas dbt, menerapkan model single-responsibility dan membuat proses debugging menjadi lebih sederhana.
Staging adalah lapisan yang paling dekat dengan data mentah. Tugasnya terbatas: mengganti nama kolom, melakukan casting tipe data, dan menyaring baris yang tidak valid. Tidak ada join, tidak ada agregasi.
-- models/staging/stg_orders.sql
WITH source AS (
SELECT * FROM {{ source('ecommerce', 'raw_orders') }}
)
SELECT
id AS order_id,
customer_id,
CAST(order_date AS DATE) AS order_date,
CAST(amount AS DECIMAL(10, 2)) AS order_amount,
LOWER(status) AS order_status
FROM source
WHERE id IS NOT NULLIntermediate menerapkan logika bisnis — join, agregasi, dan window function. Model ini mereferensi staging model melalui ref(), yang mendaftarkan dependensi dalam DAG.
-- models/intermediate/int_customer_orders.sql
WITH orders AS (
SELECT * FROM {{ ref('stg_orders') }}
),
customers AS (
SELECT * FROM {{ ref('stg_customers') }}
)
SELECT
c.customer_id,
c.customer_name,
COUNT(o.order_id) AS total_orders,
SUM(o.order_amount) AS lifetime_value,
MIN(o.order_date) AS first_order_date,
MAX(o.order_date) AS last_order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_nameMarts adalah lapisan konsumsi akhir — tabel yang bersih, terdokumentasi, dan dapat langsung diakses oleh dashboard maupun analis.
Pendekatan berlapis ini memastikan bahwa kerusakan di sumber data hanya mempengaruhi staging, bukan seluruh pipeline. Setiap lapisan dapat diuji secara independen.
Fungsi ref() dan Resolusi DAG
ref() bukan sekadar alias. Memanggil {{ ref('stg_orders') }} melakukan dua hal: menyelesaikan nama tabel yang sepenuhnya berkualifikasi pada waktu kompilasi, dan mendaftarkan edge dependensi dalam directed acyclic graph (DAG) milik dbt. Tanpa ref(), dbt tidak memiliki cara untuk menentukan urutan eksekusi.
Kesalahan umum yang sering terjadi adalah menulis nama tabel secara hardcode alih-alih menggunakan ref(). Hal ini merusak tracking dependensi dan dapat menyebabkan model berjalan sebelum dependensi upstream-nya siap.
-- Salah: referensi hardcode, tidak ada tracking dependensi
SELECT * FROM analytics.stg_orders
-- Benar: ref() mendaftarkan dependensi
SELECT * FROM {{ ref('stg_orders') }}DAG juga mendukung fitur seperti dbt run --select stg_orders+, yang menjalankan model beserta semua model di downstream-nya — berguna untuk rebuild yang ditargetkan setelah perubahan skema sumber.
Materialisasi: Memilih Strategi Penyimpanan yang Tepat
dbt menawarkan empat materialisasi bawaan, masing-masing cocok untuk pola akses dan volume data yang berbeda.
| Materialisasi | Penyimpanan | Cocok untuk | Trade-off |
|--------------|-------------|-------------|----------|
| view | Tidak ada (dihitung saat dibaca) | Transformasi ringan, dataset kecil | Pembacaan lambat untuk data besar |
| table | Rebuild tabel penuh setiap run | Model layer mart, pembacaan cepat | Rebuild semua, biaya lebih tinggi |
| incremental | Append/merge baris baru saja | Tabel fakta besar, event stream | Logika lebih kompleks, butuh unique_key |
| ephemeral | Inline sebagai CTE, tidak pernah dimaterialisasi | Logika reusable antar model | Tidak bisa di-query secara langsung |
Default-nya adalah view. Override dilakukan di blok config model atau di dbt_project.yml:
-- models/marts/fct_daily_revenue.sql
{{
config(
materialized='incremental',
unique_key='revenue_date',
incremental_strategy='merge'
)
}}
SELECT
DATE(order_date) AS revenue_date,
SUM(order_amount) AS daily_revenue,
COUNT(DISTINCT customer_id) AS unique_customers
FROM {{ ref('stg_orders') }}
WHERE order_status = 'completed'
{% if is_incremental() %}
AND order_date > (SELECT MAX(revenue_date) FROM {{ this }})
{% endif %}
GROUP BY DATE(order_date)Blok is_incremental() hanya berjalan selama build incremental — pada full refresh (dbt run --full-refresh), blok ini dilewati dan seluruh tabel dibangun ulang.
Siap menguasai wawancara Data Engineering Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Menguji Kualitas Data di Setiap Lapisan
dbt menyediakan dua kategori pengujian: generic tests yang dideklarasikan dalam YAML, dan singular tests yang ditulis sebagai file SQL mandiri yang mengembalikan baris ketika gagal.
Generic tests mencakup constraint struktural:
# models/staging/_stg_models.yml
version: 2
models:
- name: stg_orders
columns:
- name: order_id
tests:
- unique # Tidak ada order ID duplikat
- not_null # Setiap baris memiliki order ID
- name: order_status
tests:
- accepted_values:
values: ['completed', 'pending', 'cancelled', 'refunded']
- name: customer_id
tests:
- not_null
- relationships: # Pemeriksaan integritas referensial
to: ref('stg_customers')
field: customer_idSingular tests memvalidasi aturan bisnis yang tidak bisa diekspresikan oleh generic tests:
-- tests/assert_revenue_never_negative.sql
-- Mengembalikan baris dimana revenue harian negatif (seharusnya 0 baris)
SELECT
revenue_date,
daily_revenue
FROM {{ ref('fct_daily_revenue') }}
WHERE daily_revenue < 0Unit tests, yang diperkenalkan di dbt 1.8, memvalidasi logika transformasi dengan input terkontrol dan output yang diharapkan — tanpa perlu warehouse. Test ini berjalan langsung dalam fase dbt test.
Strategi pengujian harus mengikuti aliran data: pemeriksaan freshness di level source, validasi constraint skema di staging, integritas referensial di intermediate, dan assertion logika bisnis di mart.
dbt Core v1.10 dan Fusion Engine
dbt Core v1.10 memperkenalkan flag --sample untuk perintah run dan build. Flag ini menerapkan sampling berbasis waktu pada ref() dan source(), memungkinkan developer memvalidasi transformasi pada subset data tanpa biaya full build. Sangat membantu untuk iterasi pada model yang didukung tabel fakta berisi miliaran baris.
Fusion engine — rebuild total menggunakan Rust — sekarang menjadi default untuk proyek baru di dbt Cloud pada Snowflake, BigQuery, Redshift, dan Databricks. Fusion memperkenalkan semantic versioning mulai dari 2.0 dan membawa peningkatan performa signifikan pada kompilasi dan eksekusi.
Tambahan penting lainnya di 2026: spesifikasi YAML untuk Semantic Layer sebagai definisi metrik terpusat, Cost Insights (beta) untuk memperkirakan biaya komputasi warehouse per model, dan native private packages yang kini tersedia secara umum.
Macro dan Jinja untuk Logika yang Dapat Digunakan Ulang
Ketika pola SQL yang sama muncul di beberapa model, ekstrak pola tersebut ke dalam macro. Macro adalah fungsi Jinja yang disimpan di direktori macros/.
-- macros/cents_to_dollars.sql
{% macro cents_to_dollars(column_name) %}
ROUND(CAST({{ column_name }} AS DECIMAL(10, 4)) / 100, 2)
{% endmacro %}Dipanggil di model manapun:
-- models/staging/stg_payments.sql
SELECT
payment_id,
order_id,
{{ cents_to_dollars('amount_cents') }} AS amount_dollars,
payment_method
FROM {{ source('stripe', 'payments') }}Pendekatan ini menjaga codebase tetap DRY. Alternatifnya — menyalin formula konversi ke setiap model yang membutuhkannya — menciptakan overhead pemeliharaan dan inkonsistensi.
Pertanyaan Wawancara yang Sering Ditanyakan
Wawancara data engineering pada tahun 2026 semakin banyak menguji pengetahuan dbt melampaui hal-hal dasar. Berikut adalah pertanyaan-pertanyaan yang membedakan kandidat, diambil dari pola yang terlihat di berbagai perusahaan yang menggunakan modern data stack.
T: Model incremental memproses ulang seluruh tabel semalam. Apa yang terjadi?
Penyebab paling umum: kolom unique_key mengandung nilai null. Ketika dbt mencoba MERGE pada key yang null, match gagal untuk setiap baris, sehingga terjadi insert duplikat. Penyebab kedua: seseorang menjalankan dbt run --full-refresh tanpa menyadari bahwa itu membangun ulang tabel dari awal. Ketiga: filter is_incremental() mereferensi kolom yang belum ada di tabel target (run pertama vs run berikutnya). Debugging dimulai dengan memeriksa SQL yang sudah dikompilasi di target/compiled/.
T: Bagaimana seharusnya pengujian dilapisi dalam proyek dbt produksi?
Pemeriksaan freshness source berjalan pertama — jika source belum diperbarui, model downstream tidak seharusnya berjalan pada data basi. Pengujian staging memvalidasi constraint skema: primary key (unique + not_null), accepted values, dan type cast. Pengujian intermediate memeriksa integritas referensial antar join. Pengujian mart menegaskan invarian bisnis: revenue >= 0, active users >= paying users, dan jumlah bagian sama dengan total. Semua test berjalan di CI pada pull request terhadap schema dev, kemudian berjalan lagi pasca-deployment di produksi dengan alerting.
T: Kapan sebuah model harus ephemeral vs view?
Model ephemeral meng-inline SQL-nya sebagai CTE ke dalam model yang mengonsumsinya — berguna untuk logika reusable yang tidak perlu di-query secara independen. View dihitung saat dibaca dan ada sebagai objek yang dapat di-query. Trade-off-nya: model ephemeral tidak bisa diuji secara langsung (tidak ada tabel untuk menjalankan assertion) dan tidak muncul di data lineage tool. Gunakan ephemeral untuk logika helper internal; gunakan view untuk apapun yang membutuhkan pengujian atau monitoring independen.
T: Jelaskan perbedaan antara source() dan ref().
source() menunjuk ke tabel mentah yang didefinisikan di file sources.yml — ini adalah tabel yang tidak dikelola oleh dbt. ref() menunjuk ke model dbt lainnya. Keduanya mendaftarkan dependensi DAG, tetapi source() juga memungkinkan pemeriksaan freshness (dbt source freshness), yang tidak dilakukan oleh ref(). Menggunakan source() untuk tabel mentah dan ref() untuk semua hal lainnya bukan pilihan — ini adalah cara dbt mengetahui apa yang dikontrolnya dan apa yang tidak.
Untuk kumpulan pertanyaan wawancara data engineering yang lebih luas, termasuk topik seperti arsitektur pipeline ETL vs ELT, modul latihan SharpSkill tentang dbt fundamentals dan advanced dbt patterns mencakup konsep-konsep ini dengan latihan interaktif.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Kesimpulan
- dbt mentransformasi data mentah di warehouse melalui pernyataan SQL SELECT yang dikompilasi secara otomatis menjadi DDL — struktur berlapis staging/intermediate/mart menjaga setiap model tetap fokus pada satu tanggung jawab
- Fungsi
ref()adalah tulang punggung manajemen dependensi: menyelesaikan nama tabel dan membangun DAG yang mengontrol urutan eksekusi - Materialisasi incremental mengurangi biaya pada tabel besar, tetapi membutuhkan penanganan hati-hati terhadap
unique_key, nilai null, dan filteris_incremental() - Pengujian harus mengikuti aliran data — freshness source, constraint skema di staging, integritas referensial di intermediate, assertion logika bisnis di level mart
- dbt Core v1.10 menghadirkan flag
--sampleuntuk iterasi lebih cepat, sementara Fusion engine (berbasis Rust, versi 2.0) kini menjadi default di dbt Cloud - Pertanyaan wawancara tentang dbt berfokus pada debugging kegagalan nyata (reprocessing incremental, null key, source basi) bukan definisi — pengalaman langsung dengan SQL terkompilasi dan CI pipeline lebih penting daripada jawaban yang dihafal
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

ETL vs ELT di 2026: Panduan Lengkap Arsitektur Data Pipeline
Pelajari perbedaan mendasar antara ETL dan ELT dalam data engineering modern. Panduan komprehensif arsitektur data pipeline dengan contoh kode Python dan dbt untuk membangun sistem yang scalable.

25 Pertanyaan Wawancara Data Engineering Terpopuler di Tahun 2026
Panduan komprehensif berisi 25 pertanyaan wawancara data engineering yang paling sering diajukan di tahun 2026, dilengkapi jawaban mendalam, contoh kode, dan strategi persiapan untuk kandidat di semua level.

Apache Spark 4: Fitur Baru, Structured Streaming, dan Pertanyaan Interview
Panduan lengkap Apache Spark 4 mencakup ANSI SQL mode, VARIANT data type, Real-Time Mode streaming, Spark Connect, dan pertanyaan interview data engineering terkini.