Kebutuhan analitik pada Bagian 1 kini kita turunkan menjadi model data konkret. Star schema dipilih karena seluruh pertanyaan bisnis berbentuk agregasi yang dipotong menurut beberapa atribut, pola yang paling nyaman dilayani tabel fakta di tengah dan tabel dimensi di sekelilingnya, seperti dibahas pada chapter Star Schema dan Fact Table dan Dimension Table. Hasil bagian ini adalah spesifikasi lima tabel yang menjadi acuan seluruh kode pada bagian berikutnya. Kita tidak menulis kode pemuatan apa pun dulu; perubahan pada tahap desain jauh lebih murah daripada setelah pipeline berjalan.
Diagram Star Schema #
Empat garis relasi membaca fakta ke dimensi: satu baris pesanan terjadi pada tepat satu tanggal, dilakukan tepat satu pelanggan (versi tertentu), memuat tepat satu produk, dan terjadi di tepat satu toko. Tidak ada tabel jembatan dan tidak ada dimensi bersarang; kebutuhan kita memang selesai pada bentuk bintang sederhana ini. Model alternatif snowflake seperti pada chapter Snowflake Schema akan memecah dim_produk menjadi tabel kategori terpisah, tetapi kardinalitas kategori kita hanya empat sehingga pemecahan hanya menambah join tanpa menghemat penyimpanan berarti.
Spesifikasi dim_pelanggan #
| Kolom | Tipe | Keterangan |
|---|---|---|
pelanggan_sk | INTEGER | surrogate key, lihat chapter Surrogate Key |
nk_hash | VARCHAR | md5 dari pelanggan_id, pelacak natural key |
attr_hash | VARCHAR | md5 gabungan atribut, pendeteksi perubahan |
pelanggan_id | VARCHAR | natural key dari sistem operasional |
nama, email | VARCHAR | atribut deskriptif |
kota, segmen | VARCHAR | atribut analitik yang bisa berubah |
valid_from, valid_to | DATE | masa berlaku versi (SCD Type 2) |
is_current | BOOLEAN | penanda versi terkini |
Kolom valid_from, valid_to, dan is_current disiapkan sejak awal meski baru dimanfaatkan pada Bagian 6. Menambahkan kolom ini di kemudian hari pada tabel yang sudah berisi fakta berarti menulis ulang sejarah; menyiapkannya sejak awal hampir tanpa biaya.
Spesifikasi fact_pesanan #
| Kolom | Tipe | Keterangan |
|---|---|---|
pesanan_id | VARCHAR | degenerate dimension: nomor pesanan tanpa tabel dimensi |
baris | INTEGER | nomor baris pesanan, pembeda grain |
tanggal_sk, pelanggan_sk, produk_sk, toko_sk | INTEGER | foreign key ke dimensi |
jumlah | INTEGER | banyaknya item |
harga_satuan | BIGINT | harga transaksi, bukan harga master |
diskon | BIGINT | potongan rupiah pada baris pesanan |
total | BIGINT | jumlah * harga_satuan - diskon |
status | VARCHAR | selesai, dibatalkan, dikembalikan |
pesanan_id dan baris disebut degenerate dimension karena berperan sebagai kunci analitis, misalnya menghitung pesanan unik, tetapi tidak memiliki tabel dimensi sendiri. Menyimpan nomor pesanan langsung pada fact table adalah praktik standar Kimball untuk dimensi berumur satu transaksi.
Klasifikasi Measure #
Tiga measure bersifat additive dan boleh dijumlahkan pada semua dimensi. Satu measure tidak:
| Kolom | Sifat | Alasan |
|---|---|---|
jumlah | additive | menjumlah item lintas dimensi bermakna |
total | additive | menjumlah nilai rupiah bermakna |
diskon | additive | menjumlah potongan bermakna |
harga_satuan | non-additive | rata-rata atau nilai tunggal saja; menjumlah harga satuan menghasilkan angka tanpa makna |
Klasifikasi ini menentukan ekspresi metrik pada Bagian 1: GMV memakai SUM(total), bukan SUM(harga_satuan) * SUM(jumlah), karena total sudah menyimpan hasil kali per baris termasuk diskon.
Keputusan Kunci pada Desain #
Tiga keputusan lain kita kunci bersama-sama. Pertama, dim_tanggal memakai smart key YYYYMMDD berbentuk INTEGER sehingga rentang tanggal dapat disaring tanpa join, misalnya tanggal_sk BETWEEN 20250301 AND 20250331. Kedua, seluruh dimensi lain memakai surrogate key INTEGER yang diterbitkan oleh pipeline, bukan kunci bisnis dari sistem sumber, agar perubahan pada sistem sumber tidak merusak relasi fakta. Ketiga, gudang data ini tidak memasang constraint PRIMARY KEY maupun FOREIGN KEY pada DuckDB; integritas dijaga pemeriksaan kualitas data pada Bagian 7, mengikuti praktik umum gudang data yang mengutamakan kecepatan pemuatan.
Spesifikasi lima tabel telah lengkap. Pada Bagian 3 kita mulai menulis kode: tabel dimensi pertama beserta mekanisme surrogate key dan pelacakan hash.