Sepanjang section ini kita menulis transformasi tanpa mempermasalahkan lokasinya, padahal pilihan ETL (transform sebelum pemuatan) dan ELT (transform setelah data mentah masuk warehouse) menentukan arsitektur, biaya, dan bahkan komposisi tim data. Pilihan yang keliru membuat kita memelihara cluster Spark untuk data 5 GB per hari, atau sebaliknya membakar kredit warehouse untuk transform yang lebih murah di compute terpisah. Bab penutup ini merangkum seluruh materi menjadi satu kerangka keputusan yang bisa dipakai saat merancang pipeline pertama maupun saat mengevaluasi arsitektur yang sudah berjalan.
ETL vs ELT dalam Satu Tabel #
| Aspek | ETL (transform sebelum muat) | ELT (transform setelah muat) |
|---|---|---|
| Lokasi transform | server/cluster terpisah (Spark, Python worker) | di dalam warehouse (SQL, dbt) |
| Bentuk data di warehouse | sudah bersih dan bentuk final | data mentah lengkap, transformasi sebagai kode SQL |
| Tooling khas | Spark, Airflow + Python job | dbt di atas DuckDB, BigQuery, Snowflake |
| Keahlian tim | software engineering, data engineering | analisis SQL kuat, analytics engineering |
| Biaya compute | infra terpisah yang harus dikelola | kredit warehouse, bayar sesuai pemakaian |
| Masking PII sebelum masuk gudang | alami, di pipeline | butuh kebijakan akses ketat di warehouse |
| Elastisitas | terbatas kapasitas cluster yang disiapkan | mengikuti elastisitas warehouse |
Karakter penting ELT: data mentah tersimpan utuh di warehouse sehingga transformasi dapat diulang dan diverifikasi kapan saja — seluruh teknik pada chapter Idempotent Transformation hingga Pemrosesan Ulang Data berlaku langsung di atas data yang sama. Karakter penting ETL: data sensitif bisa disamarkan sebelum meninggalkan zona sumber, dan transform non-SQL (memanggil API, model ML) berjalan wajar di pipeline.
Kerangka Keputusan #
Keputusan turun ke lima pertanyaan: apakah warehouse analitik sudah tersedia, seberapa besar volume harian data, apakah tim analis kuat di SQL, apakah regulasi mewajibkan masking sebelum data masuk warehouse, dan apakah transformasi butuh layanan non-SQL. Diagram berikut merangkum alurnya:
ELT di Praktik dengan dbt #
Tool de-facto untuk ELT adalah dbt: transformasi ditulis sebagai model SQL yang berversi di Git, dirujuk antar-model lewat ref(), dan dijalankan langsung di warehouse. Model berikut membangun agregat penjualan harian kita secara incremental — perilaku yang sama dengan Chapter Incremental Transformation, hanya kali ini dikelola dbt (berjalan di dbt Core 1.12, tidak dieksekusi di bab ini):
-- models/penjualan_harian.sql
{{ config(materialized='incremental', unique_key='tanggal') }}
select
substr(event_time, 1, 10) as tanggal,
count(*) as jumlah_pesanan,
sum(qty * harga) as total_pendapatan
from {{ ref('pesanan_bersih') }}
{% if is_incremental() %}
-- eksekusi berikutnya: proses ulang hari berjalan + hari baru saja
where event_time >= (select max(tanggal) from {{ this }})
{% endif %}
group by 1Eksekusi pertama dbt run membangun tabel penuh dari pesanan_bersih. Eksekusi berikutnya mengaktifkan blok is_incremental(): hanya baris sumber sejak tanggal agregat terakhir yang diproses (perbandingan awalan tanggal ISO berlaku leksikografis), lalu dbt menggabungkan hasil menurut unique_key tanggal dengan mengganti baris lama — semantik replace yang aman diulang. Bendera dbt run --full-refresh memaksa full rebuild, mekanisme reprocess yang kita bahas pada Chapter *Pemrosesan Ulang Data`. Detail lengkap model incremental ada di dokumentasi dbt
, dan rujukan utama tool-nya di docs.getdbt.com
.
Menerapkan Kerangka: Tiga Studi Kasus #
Fungsi berikut menerjemahkan lima pertanyaan di atas menjadi skor sederhana; selisih skor menentukan rekomendasi, dan selisih tipis menghasilkan hybrid.
def rekomendasi(volume_gb_per_hari, warehouse_analitik, tim_analisis_sql,
wajib_masking, transform_non_sql):
"""Kerangka keputusan sederhana ETL vs ELT (ilustrasi)."""
skor_elt = 0
skor_etl = 0
alasan_elt = []
alasan_etl = []
if warehouse_analitik:
skor_elt += 2
alasan_elt.append("warehouse analitik sudah tersedia")
else:
skor_etl += 1
alasan_etl.append("belum ada warehouse analitik")
if tim_analisis_sql:
skor_elt += 1
alasan_elt.append("tim analis kuat di SQL (dbt)")
if volume_gb_per_hari <= 100:
skor_elt += 1
alasan_elt.append("volume kecil, warehouse menangani tanpa infra tambahan")
elif volume_gb_per_hari >= 1000:
skor_etl += 1
alasan_etl.append("volume besar, compute terpisah lebih ekonomis")
if wajib_masking:
skor_etl += 2
alasan_etl.append("PII wajib disamarkan sebelum masuk warehouse")
if transform_non_sql:
skor_etl += 1
alasan_etl.append("transform butuh layanan non-SQL (API, model ML)")
selisih = skor_elt - skor_etl
if selisih >= 2:
pola = "ELT"
elif selisih <= -2:
pola = "ETL"
else:
pola = "HYBRID"
return pola, skor_elt, skor_etl, alasan_elt, alasan_etl
studi_kasus = [
("startup e-commerce lokal", {
"volume_gb_per_hari": 5,
"warehouse_analitik": True,
"tim_analisis_sql": True,
"wajib_masking": False,
"transform_non_sql": False,
}),
("bank dengan regulasi ketat", {
"volume_gb_per_hari": 800,
"warehouse_analitik": False,
"tim_analisis_sql": False,
"wajib_masking": True,
"transform_non_sql": True,
}),
("retailer nasional", {
"volume_gb_per_hari": 2000,
"warehouse_analitik": True,
"tim_analisis_sql": True,
"wajib_masking": True,
"transform_non_sql": False,
}),
]
for nama, faktor in studi_kasus:
pola, skor_elt, skor_etl, alasan_elt, alasan_etl = rekomendasi(**faktor)
print(f"=== {nama} ===")
print(f" skor ELT {skor_elt} vs ETL {skor_etl} -> rekomendasi: {pola}")
for alasan in alasan_elt:
print(f" ELT: {alasan}")
for alasan in alasan_etl:
print(f" ETL: {alasan}")Output yang Dihasilkan:
=== startup e-commerce lokal ===
skor ELT 4 vs ETL 0 -> rekomendasi: ELT
ELT: warehouse analitik sudah tersedia
ELT: tim analis kuat di SQL (dbt)
ELT: volume kecil, warehouse menangani tanpa infra tambahan
=== bank dengan regulasi ketat ===
skor ELT 0 vs ETL 4 -> rekomendasi: ETL
ETL: belum ada warehouse analitik
ETL: PII wajib disamarkan sebelum masuk warehouse
ETL: transform butuh layanan non-SQL (API, model ML)
=== retailer nasional ===
skor ELT 3 vs ETL 3 -> rekomendasi: HYBRID
ELT: warehouse analitik sudah tersedia
ELT: tim analis kuat di SQL (dbt)
ETL: volume besar, compute terpisah lebih ekonomis
ETL: PII wajib disamarkan sebelum masuk warehouseMari kita baca ketiga hasil tersebut. Startup dengan 5 GB per hari dan tim SQL yang sudah ada tidak membutuhkan infra tambahan: muat data mentah ke warehouse, lalu seluruh transformasi berjalan sebagai model dbt — bahkan warehouse analitik ringan seperti DuckDB sudah memadai untuk mulai. Bank justru di ujung lain: data pribadi nasabah wajib disamarkan sebelum meninggalkan zona sumber, warehouse analitik terpusat belum tersedia, dan transformasi melibatkan enrichment non-SQL — semua faktor mengarah ke ETL on-premise. Retailer nasional mendapat skor seimbang: volume 2 TB per hari membuat kredit warehouse mahal untuk transform berat, tetapi tim SQL kuat dan warehouse sudah berdiri; jawaban yang tepat adalah hybrid — masking dan validasi ringan di pipeline, agregat dan business logic di warehouse.
Kapan Hybrid Menjadi Jawaban #
Hybrid bukan kompromi yang malas, melainkan pembagian kerja yang sadar: pipeline melakukan transformasi murah yang harus dekat sumber (validasi format, masking PII, normalisasi satuan), sedangkan warehouse menangani transformasi berat yang iteratif dan dianalisis bersama (join, agregat, business logic). Pola tersebut juga menjaga kualitas: hasil pipeline tetap bisa direkonsiliasi seperti pada Chapter Data Reconciliation, dan data mentah tetap utuh di warehouse untuk reprocess di masa depan.
Dengan kerangka ini, pertanyaan “ETL atau ELT?” tidak lagi dijawab dengan selera, melainkan dengan data: volume, biaya, tooling, tim, dan regulasi. Setelah pola transformasi dipilih, langkah berikutnya adalah membentuk data hasil transformasi menjadi model analitik yang enak ditanyakan — tugas utama Course Data Modeling dan Data Warehouse.