Section Data Modeling dan Warehouse sudah memberi kita kosakata lengkap untuk menata tabel analitik: dimensional modeling, star schema, fact table, dimension table, hingga slowly changing dimensions. Section ini berpindah dari konsep ke praktik: kita membangun lapisan analytics tersebut sebagai kode menggunakan dbt, dari struktur model, incremental models, snapshots, testing, hingga integrasi ke alat business intelligence. Sebelum menyentuh dbt, chapter pembuka ini menuntaskan satu keputusan yang menentukan isi seluruh section: bentuk tabel apa yang kita bangun, dan untuk siapa tabel tersebut dibuat. Pekerjaan mengambil keputusan tersebut adalah analytical data modeling.

Posisi Modeling dalam Alur Analytics #

Alur kerja analytics bergerak dari data mentah menuju keputusan bisnis. Data dari aplikasi operasional TokoKita mendarat di layer raw apa adanya, lalu analytical data modeling merancang tabel perantara yang memetakan data mentah menjadi struktur siap tanya: dimensi, fakta, atau wide table. Hasil pemodelan dikonsumsi dua arah — dashboard BI untuk pembaca laporan, dan SQL ad-hoc untuk analis:

Pemodelan analitik berbeda tujuan dari pemodelan operasional. Skema operasional mengejar konsistensi transaksi lewat normalisasi, sedangkan skema analitik mengejar kemudahan membaca laporan — asas yang sudah dibedah Chapter Dimensional Modeling melalui empat langkah desain Kimball. Chapter Star Schema dan Snowflake Schema kemudian menunjukkan wujud fisik dari desain tersebut, jadi materi tersebut tidak diulang di sini. Pertanyaan yang tersisa untuk praktik: di antara beberapa pendekatan pemodelan, mana yang paling cocok untuk alat BI modern yang kita pakai?

Pendekatan Modeling yang Sering Dipakai #

PendekatanBentuk hasilKekuatanBatasan
Kimball dimensionalstar schema per proses bisnisquery analitik pendek dan cepat, dimensi dipakai ulangmenuntut disiplin desain grain dan dimensi
Inmon (3NF korporat)model entitas perusahaan, mart menyusulsatu sumber kebenaran ternormalisasinilai baru terasa lama, laporan butuh banyak join
Wide table / One Big Table (OBT)satu tabel lebar per analisispaling ramah alat BI, tanpa joinduplikasi storage, perubahan dimensi menular ke seluruh tabel

Dalam praktik, ketiganya jarang berdiri sendiri. Pola yang umum: star schema sebagai inti warehouse, lalu OBT dibangun di mart untuk konsumen dashboard — persis pola mart per departemen yang sudah kita bangun di Chapter Data Marts. Section ini mengikuti pola campuran tersebut, dan dbt tidak memaksa pilihan tertentu karena dbt hanya menjalankan SQL yang kita tulis. Perbandingan filosofis Inmon versus Kimball sudah dibedah pada Chapter Dimensional Modeling; tabel di atas menimbang ketiganya dari sudut konsumen akhir, yaitu alat BI dan analis yang membaca tabel tersebut setiap hari.

Wide Table untuk Alat BI #

Alat BI — Looker, Tableau, Metabase, hingga spreadsheet — paling nyaman membaca satu tabel lebar: analis tinggal menyeret kolom tanpa menulis join. OBT pada dasarnya adalah star schema yang sudah di-join lebih dulu. Skrip berikut membangun obt_pesanan dari star schema kecil di atas DuckDB, lalu mengajukan pertanyaan bisnis yang sama dari dua sisi; blok di bawah memotong bagian awal skrip yang membuat tiga tabel star berisi lima pesanan Budi, Siti, dan Dewi:

python
print("=== pertanyaan bisnis via star schema (3 tabel, 2 JOIN) ===")
rows = con.execute("""
SELECT p.kota, SUM(f.qty * f.harga) AS gmv
FROM fact_pesanan f
JOIN dim_pelanggan p ON p.sk_pelanggan = f.sk_pelanggan
JOIN dim_produk    r ON r.sk_produk   = f.sk_produk
WHERE r.kategori = 'pakaian'
GROUP BY p.kota ORDER BY gmv DESC
""").fetchall()
for kota, gmv in rows:
    print(f"  {kota:8s} Rp{gmv}")

print()
print("=== bangun OBT: star yang sudah di-join jadi satu tabel lebar ===")
con.execute("""
CREATE TABLE obt_pesanan AS
SELECT f.id_pesanan, f.tanggal, f.qty, f.harga,
       f.qty * f.harga        AS total,
       p.email, p.kota, p.segmen,
       r.nama_produk, r.kategori
FROM fact_pesanan f
JOIN dim_pelanggan p ON p.sk_pelanggan = f.sk_pelanggan
JOIN dim_produk    r ON r.sk_produk   = f.sk_produk
""")
kolom = [c[0] for c in con.execute(
    "SELECT column_name FROM duckdb_columns() "
    "WHERE table_name = 'obt_pesanan' ORDER BY column_index"
).fetchall()]
print(f"  obt_pesanan: {con.execute('SELECT COUNT(*) FROM obt_pesanan').fetchone()[0]}"
      f" baris, {len(kolom)} kolom: {', '.join(kolom)}")

print()
print("=== pertanyaan yang sama via OBT (1 tabel, 0 JOIN) ===")
rows = con.execute("""
SELECT kota, SUM(total) AS gmv
FROM obt_pesanan
WHERE kategori = 'pakaian'
GROUP BY kota ORDER BY gmv DESC
""").fetchall()
for kota, gmv in rows:
    print(f"  {kota:8s} Rp{gmv}")

Output yang Dihasilkan:

text
=== pertanyaan bisnis via star schema (3 tabel, 2 JOIN) ===
  Bandung  Rp750000
  Jakarta  Rp250000
  Depok    Rp250000

=== bangun OBT: star yang sudah di-join jadi satu tabel lebar ===
  obt_pesanan: 5 baris, 10 kolom: id_pesanan, tanggal, qty, harga, total, email, kota, segmen, nama_produk, kategori

=== pertanyaan yang sama via OBT (1 tabel, 0 JOIN) ===
  Bandung  Rp750000
  Jakarta  Rp250000
  Depok    Rp250000

Mari kita telaah bagian penting kode di atas:

  1. Blok CREATE TABLE obt_pesanan AS: pernyataan CTAS menggabungkan fact table ke dua dimensi dalam satu langkah, sehingga atribut kota, segmen, dan kategori yang tadinya terpisah kini menjadi kolom biasa di satu tabel.
  2. Blok query OBT terakhir: filter kategori = 'pakaian' dan agregasi SUM(total) berjalan tanpa satu pun JOIN, dan hasilnya identik dengan query dari sisi star schema — bukti bahwa OBT memindahkan pekerjaan join dari saat query ke saat build.

Kenyamanan OBT datang dengan tagihan. Atribut pelanggan terduplikasi di setiap baris pesanan sehingga storage membengkak, dan setiap perubahan atribut dimensi menuntut build ulang seluruh tabel — belum lagi riwayat perubahan yang harus mengikuti aturan SCD dari Chapter Slowly Changing Dimensions.

Kapan Waktu Remodel #

Model yang baik hari ini bisa jadi tidak cocok tahun depan. Tanda-tanda bahwa model perlu dirancang ulang:

  • Query dashboard tumbuh menjadi join berlapis-lapis dan makin lambat setiap bulan.
  • Pertanyaan bisnis baru tidak terjawab oleh grain tabel yang ada.
  • Banyak dashboard mulai menyalin agregasi yang sama, masing-masing dengan rumus sedikit berbeda.
  • Sistem operasional diganti, sehingga mapping sumber ke model putus.
  • Istilah bisnis berubah — misalnya dua divisi merger dan dimensi pelanggan harus disatukan.

Kabar baiknya, pada section ini model hidup sebagai file SQL yang dikelola dbt — konsep model sebagai SQL yang dijalankan terdokumentasi di dokumentasi dbt . Remodel berarti mengubah SQL model lalu membangun ulang tabelnya, bukan menulis ulang pipeline dari nol — justru itulah alasan utama section ini memakai dbt, yang akan kita perkenalkan pada Chapter dbt.