MODUL PERTEMUAN 12
DIMENSIONAL MODELLING: STAR SCHEMA
A. INFORMASI UMUM MATA KULIAH
| Item | Keterangan |
|---|---|
| Mata Kuliah | Data Modelling |
| Kode MK | SSD1019 |
| Bobot | 3 SKS (Praktikum) |
| Semester | 4 (Empat) |
| Program Studi | Sains Data |
| Fakultas | Ekonomi dan Bisnis Islam |
| Universitas | UIN K.H. Abdurrahman Wahid Pekalongan |
| Dosen Pengampu | Mohammad Reza Maulana, M.Kom |
B. INFORMASI PERTEMUAN
B.1 Sub-CPMK Pertemuan 12
Sub-CPMK 4.1 dan 6.1: Mahasiswa mampu merancang star schema yang lengkap dan benar untuk sebuah proses bisnis â mulai dari mendefinisikan grain secara tepat, merancang tabel fakta beserta measures-nya, membangun tabel-tabel dimensi yang kaya atribut dan denormalisasi secara disengaja, hingga mengimplementasikan seluruh skema dalam bentuk DDL SQL yang siap dijalankan dan digunakan untuk query analitik.
B.2 Tujuan Pembelajaran (Learning Objectives)
Setelah mengikuti pertemuan ini, mahasiswa akan mampu:
- Menjelaskan empat langkah proses desain dimensional (Kimball Four-Step Process) dan menerapkannya secara berurutan untuk sebuah proses bisnis (C3 â Menerapkan)
- Mendefinisikan grain sebuah tabel fakta dengan tepat dan mempertahankan konsistensinya di seluruh desain (C3 â Menerapkan)
- Membedakan tiga jenis measures â additive, semi-additive, dan non-additive â dan menentukan implikasi masing-masing terhadap agregasi (C2 â Memahami)
- Menjelaskan konsep surrogate key, natural key, dan degenerate dimension beserta alasan dan cara penggunaannya (C2 â Memahami)
- Merancang tabel dimensi yang "lebar" (wide/fat), denormalisasi, dan kaya atribut yang mendukung berbagai pertanyaan analitik (C6 â Mencipta)
- Membangun dimensi waktu (date dimension) lengkap yang mendukung berbagai hierarki analitik (C3 â Menerapkan)
- Menjelaskan variasi dimensi khusus: conformed dimension, role-playing dimension, junk dimension, dan degenerate dimension (C2 â Memahami)
- Mengimplementasikan star schema lengkap dalam DDL MySQL yang benar, beserta query analitik yang mendemonstrasikan kegunaannya (C3 â Menerapkan)
B.3 Kompetensi yang Dikembangkan
| Domain | Kompetensi |
|---|---|
| Kognitif | Mendefinisikan grain dengan tepat (C3), Merancang dimensi dan fakta (C6), Membedakan jenis measures (C2) |
| Afektif | Membangun kebiasaan mendesain "untuk pembaca, bukan untuk penulis" â prioritas performa query di atas efisiensi storage; menghargai konteks analitik yang kaya |
| Psikomotorik | Menulis DDL star schema yang benar di MySQL; merancang diagram star schema menggunakan draw.io atau MySQL Workbench |
B.4 Indikator Pencapaian
Setelah mengikuti pertemuan ini, mahasiswa diharapkan mampu:
- Menerapkan empat langkah Kimball untuk sebuah proses bisnis yang diberikan
- Menuliskan grain definition yang tepat dalam satu kalimat yang jelas
- Mengklasifikasikan measures ke additive/semi-additive/non-additive dengan alasan yang benar
- Merancang dimensi pelanggan, produk, dan waktu dengan minimal 8 atribut per dimensi
- Menulis DDL lengkap (4â6 tabel) untuk sebuah star schema sederhana
- Menulis minimal 3 query analitik yang berbeda menggunakan star schema yang dirancang
B.5 Alokasi Waktu
| No | Kegiatan | Durasi | Keterangan |
|---|---|---|---|
| 1 | Pembukaan & Review Singkat P11 | 5 menit | Jembatan konseptual |
| 2 | Aktivitas Pemantik: "Sebelum Mendesain, Tanya Dulu!" | 10 menit | Membangun intuisi grain |
| 3 | Materi 1: Empat Langkah Desain Dimensional (Kimball) | 15 menit | Framework utama |
| 4 | Materi 2: Grain â Keputusan Paling Fundamental | 20 menit | + latihan singkat |
| 5 | Materi 3: Tabel Fakta & Tiga Jenis Measures | 20 menit | Ceramah + contoh |
| 6 | Break | 10 menit | â |
| 7 | Materi 4: Tabel Dimensi â Merancang Konteks yang Kaya | 25 menit | Ceramah + praktikum |
| 8 | Materi 5: Dimensi Waktu â Fondasi Semua Analitik Temporal | 15 menit | Ceramah + DDL |
| 9 | Materi 6: Variasi Dimensi Khusus | 10 menit | Ringkas + contoh |
| 10 | Praktikum: Rancang Star Schema dari Nol | 20 menit | Kelompok |
| 11 | Kuis Penutup, Presentasi Singkat & Briefing Tugas Proyek | 15 menit | â |
| Total | 165 menit | (termasuk break) |
C. MATERI PEMBELAJARAN
C.1 Jembatan dari Pertemuan 11
Recap (5 menit): Di pertemuan 11, kita memahami MENGAPA dunia analitik membutuhkan sistem yang berbeda dari OLTP. Kita belajar empat karakteristik data warehouse (Inmon), proses ETL sebagai jembatan, dan berkenalan singkat dengan konsep faktaâdimensi.
APA YANG SUDAH KITA TAHU:
â OLTP â dirancang untuk menulis (write-heavy), normalized, cepat per transaksi
â OLAP/DW â dirancang untuk membaca (read-heavy), denormalized, cepat per agregasi
â Data warehouse memiliki 4 karakteristik Inmon
â ETL menjembatani OLTP ke DW
â Dimensional thinking: dunia dibagi menjadi FAKTA dan DIMENSI
PERTANYAAN YANG BELUM TERJAWAB SECARA DETAIL:
â Bagaimana TEPATNYA cara merancang skema warehouse dari awal?
â "Grain" itu apa dan bagaimana menentukan yang tepat?
â Bagaimana membangun tabel dimensi yang benar-benar berguna?
â Bagaimana mengimplementasikan semua ini dalam SQL?
â Itulah yang akan kita jawab di Pertemuan 12!C.2 Aktivitas Pemantik â "Sebelum Mendesain, Tanya Dulu!"
Instruksi (10 menit): Dosen menampilkan skenario berikut. Mahasiswa diminta membandingkan dua kandidat desain dan mendiskusikan mana yang lebih tepat â SEBELUM dosen menjelaskan teori grain.
Skenario: Sistem penjualan apotek. Seorang data engineer mengusulkan dua desain tabel fakta:
DESAIN A â Grain: Satu baris per pesanan (per struk)
âââââââââââââââŦââââââââââââââââââŦâââââââââââââââââââââââââââââââââââââââââââââââ
â kunci_waktu â kunci_pelanggan â kunci_apoteker â total_transaksi â jml_item â
âââââââââââââââŧââââââââââââââââââŧâââââââââââââââââŧââââââââââââââââââŧââââââââââââ¤
â 20240315 â 1001 â 3 â 285.000 â 4 â
â 20240315 â 1002 â 5 â 67.500 â 1 â
â 20240315 â 1001 â 3 â 150.000 â 2 â
âââââââââââââââ´ââââââââââââââââââ´âââââââââââââââââ´ââââââââââââââââââ´ââââââââââââ
DESAIN B â Grain: Satu baris per item per pesanan (per baris struk)
âââââââââââââââŦââââââââââââââââââŦâââââââââââââââââŦâââââââââââââââŦââââââŦââââââââââââ
â kunci_waktu â kunci_pelanggan â kunci_apoteker â kunci_obat â qty â subtotal â
âââââââââââââââŧââââââââââââââââââŧâââââââââââââââââŧâââââââââââââââŧââââââŧââââââââââââ¤
â 20240315 â 1001 â 3 â OBT-0091 â 2 â 120.000 â
â 20240315 â 1001 â 3 â OBT-0045 â 1 â 85.000 â
â 20240315 â 1001 â 3 â OBT-0123 â 3 â 80.000 â
â 20240315 â 1002 â 5 â OBT-0045 â 1 â 67.500 â
âââââââââââââââ´ââââââââââââââââââ´âââââââââââââââââ´âââââââââââââââ´ââââââ´ââââââââââââPertanyaan Pemantik:
- Dengan Desain A, bisakah kita menjawab: "Obat apa yang paling sering dibeli bersamaan?" â Mengapa?
- Dengan Desain B, bisakah kita menjawab: "Berapa rata-rata jumlah item per pesanan?" â Bagaimana caranya?
- Jika manajer kemudian meminta analisis per jenis obat, mana desain yang lebih siap?
- Apa kelebihan dan kekurangan masing-masing desain?
Insight Kunci yang Dosen Ungkap Setelah Diskusi: "Desain B (grain lebih atomik) hampir selalu lebih fleksibel. Analisis per pesanan masih bisa dijawab dari Desain B dengan SUM dan GROUP BY. Tapi analisis per obat TIDAK BISA dijawab dari Desain A karena informasi obat tidak ada sama sekali. Ini adalah inti dari filosofi grain: pilih grain SEPECIFIK mungkin dalam proses bisnis yang masuk akal. Inilah yang akan kita pelajari secara sistematis sekarang."
C.3 Materi 1: Empat Langkah Desain Dimensional â Kimball's Four-Step Process
Ralph Kimball, pionir dimensional modelling, mengusulkan proses desain yang harus dilakukan secara BERURUTAN. Mengubah urutan atau melewatkan langkah akan menghasilkan desain yang tidak konsisten.
EMPAT LANGKAH DESAIN DIMENSIONAL (KIMBALL):
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â LANGKAH 1: PILIH PROSES BISNIS â
â "Business process apa yang akan dimodelkan?" â
â â
â â Proses bisnis = aktivitas organisasi yang menghasilkan â
â data terukur â
â â Satu model dimensional = satu proses bisnis â
â â Contoh proses bisnis: â
â âĸ Penjualan (retail/e-commerce) â
â âĸ Pengiriman pesanan (logistik) â
â âĸ Kunjungan pasien (rumah sakit) â
â âĸ Pengambilan mata kuliah (akademik) â
â âĸ Klaim asuransi (finansial) â
â â
â â BUKAN: "analisis bisnis" atau "laporan manajemen" â
â â Terlalu abstrak. Tanya: aktivitas spesifik apa? â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â LANGKAH 2: DEKLARASIKAN GRAIN â
â "Satu baris di tabel fakta mewakili APA?" â
â â
â â Grain = tingkat detail paling atomik yang akan â
â disimpan di tabel fakta â
â â Harus dinyatakan dalam SATU KALIMAT yang jelas â
â â Semua dimensi dan measures harus konsisten dgn grain â
â â
â PALING PENTING dari keempat langkah! â
â Kesalahan grain = fondasi yang salah â desain ulang total â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â LANGKAH 3: IDENTIFIKASI DIMENSI â
â "Konteks apa yang memberi makna pada setiap fakta?" â
â â
â â Dimensi = "label" untuk fakta â
â â Tanyakan: Siapa? Apa? Kapan? Di mana? Mengapa? Bagaimanaâ
â â Setiap dimensi harus KONSISTEN dengan grain yang sudah â
â dideklarasikan di Langkah 2 â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â LANGKAH 4: IDENTIFIKASI FAKTA (MEASURES) â
â "Apa yang diukur dari kejadian bisnis ini?" â
â â
â â Measures = nilai numerik yang bisa diagregasi â
â â Setiap measure harus ada di SETIAP baris (pada grain â
â yang sudah ditentukan) â bukan hanya di sebagian baris â
â â Tentukan tipe: additive / semi-additive / non-additive â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââContoh Penerapan Empat Langkah â Toko Batik Online:
Langkah 1 â Proses Bisnis:
"Penjualan batik melalui platform e-commerce"
Langkah 2 â Grain:
"Satu baris mewakili satu item baris (line item) dalam satu
pesanan pelanggan pada satu tanggal transaksi"
(= satu SKU dalam satu pesanan = level paling atomik dari transaksi)
Langkah 3 â Dimensi:
âĸ dim_waktu â KAPAN transaksi terjadi?
âĸ dim_pelanggan â SIAPA yang membeli?
âĸ dim_produk â APA yang dibeli (SKU)?
âĸ dim_lokasi â DI MANA (kota pengiriman)?
âĸ dim_kanal â MELALUI APA pembelian dilakukan? (web, app, marketplace)
Langkah 4 â Measures (Fakta):
âĸ qty â Jumlah unit yang dibeli (additive)
âĸ harga_satuan â Harga per unit saat transaksi (non-additive)
âĸ diskon â Nominal diskon yang diberikan (additive)
âĸ revenue_bersih â qty à harga_satuan â diskon (additive)
âĸ biaya_kirim â Ongkos kirim untuk item ini (additive)C.4 Materi 2: Grain â Keputusan Paling Fundamental
C.4.1 Mengapa Grain Adalah Segalanya
GRAIN YANG SALAH = FONDASI YANG RETAK
Kesalahan grain tidak bisa diperbaiki dengan menambah kolom atau
mengubah nama tabel. Ia harus redesign dari awal, termasuk:
â ETL pipeline harus dibangun ulang
â Semua query yang sudah ada harus ditulis ulang
â Laporan historis bisa berubah hasilnya
TIGA ATURAN GRAIN (Kimball):
1. Deklarasikan grain SEBELUM memilih dimensi atau measures
2. Pilih grain yang PALING ATOMIK yang masuk akal secara bisnis
3. Semua measures dalam satu tabel fakta HARUS ada pada grain yang samaC.4.2 Grain yang Terlalu Tinggi vs Terlalu Rendah
ILUSTRASI: Sistem Perpustakaan
GRAIN TERLALU TINGGI (aggregate grain):
"Satu baris per anggota per bulan"
â Kolom: kunci_anggota, kunci_bulan, total_buku_dipinjam, total_denda
MASALAH:
â Tidak bisa tahu buku apa yang dipinjam
â Tidak bisa analisis per kategori buku
â Tidak bisa tahu pola peminjaman di hari tertentu
â Sekali grain ditetapkan, detail sudah hilang â tidak bisa "drill down" lagi!
GRAIN TERLALU RENDAH (unnecessarily granular):
"Satu baris per halaman yang dibaca anggota"
â Kolom: kunci_anggota, kunci_buku, nomor_halaman, waktu_baca
MASALAH:
â Tidak realistis (data ini tidak tersedia)
â Volume data sangat besar tanpa nilai bisnis tambahan
â Pemborosan storage
GRAIN YANG TEPAT:
"Satu baris mewakili satu transaksi peminjaman satu buku oleh satu anggota"
â Kolom: kunci_waktu, kunci_anggota, kunci_buku, durasi_pinjam_hari,
denda, kunci_petugas
KENAPA TEPAT:
â Bisa roll up ke bulan, kuartal, tahun (via dim_waktu)
â Bisa analisis per anggota, per buku, per kategori buku
â Bisa drill down ke setiap transaksi individual
â Volume data realistis dan tersediaC.4.3 Grain Berbeda = Tabel Fakta Berbeda
PRINSIP FUNDAMENTAL:
Jangan mencampur grain yang berbeda dalam satu tabel fakta!
CONTOH MASALAH (Sistem Hotel):
"Fakta_Pemesanan" berisi:
â total_harga_kamar (grain: satu baris per pemesanan)
â biaya_room_service (grain: satu baris per item room service)
â biaya_laundry (grain: satu baris per pakaian)
MASALAH: Grain tidak konsisten!
â total_harga_kamar muncul berulang kali untuk satu pemesanan
jika ada banyak item room service
â Agregasi menjadi salah (double-counting)
SOLUSI â BUAT DUA TABEL FAKTA TERPISAH:
fakta_pemesanan
Grain: satu baris per pemesanan kamar
Measures: total_harga_kamar, lama_menginap, deposit
fakta_transaksi_tambahan
Grain: satu baris per transaksi layanan tambahan
Measures: qty, harga_satuan, subtotal, jenis_layanan
â Kedua tabel bisa di-JOIN saat query jika diperlukanC.4.4 Latihan Singkat: Evaluasi Grain (5 menit)
Evaluasi grain berikut: mana yang terlalu tinggi, terlalu rendah, atau tepat? Berikan alasan!
| No | Sistem | Grain yang Diusulkan | Evaluasi |
|---|---|---|---|
| 1 | E-commerce | "Satu baris per hari per toko" | ? |
| 2 | Klinik | "Satu baris per layanan medis per kunjungan pasien" | ? |
| 3 | Bank | "Satu baris per rekening per bulan" | ? |
| 4 | Kampus | "Satu baris per mahasiswa per matakuliah per semester" | ? |
| 5 | Logistik | "Satu baris per paket dalam satu pengiriman" | ? |
C.5 Materi 3: Tabel Fakta & Tiga Jenis Measures
C.5.1 Anatomi Tabel Fakta
TABEL FAKTA TERDIRI DARI DUA JENIS KOLOM:
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â FAKTA_PENJUALAN â
â â
â KUNCI ASING (Foreign Keys) â referensi ke dimensi â
â ââââââââââââââââââââââââââââââââââââââââââââââââ â
â kunci_waktu INT (FK â dim_waktu.kunci_waktu) â
â kunci_pelanggan INT (FK â dim_pelanggan.kunci_pelanggan) â
â kunci_produk INT (FK â dim_produk.kunci_produk) â
â kunci_lokasi INT (FK â dim_lokasi.kunci_lokasi) â
â kunci_kanal INT (FK â dim_kanal.kunci_kanal) â
â â
â MEASURES (Nilai yang Diukur) â angka-angka bisnis â
â ââââââââââââââââââââââââââââââââââââââââââââââââ â
â qty SMALLINT â
â harga_satuan DECIMAL(15,2) â
â diskon DECIMAL(15,2) â
â revenue_bersih DECIMAL(15,2) â
â biaya_kirim DECIMAL(15,2) â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
KARAKTERISTIK TABEL FAKTA:
â Biasanya NARROW (sedikit kolom â terutama FK dan measures)
â Biasanya TALL (sangat banyak baris â jutaan hingga miliar)
â Tidak ada data deskriptif â semua deskripsi ada di dimensi
â PK biasanya adalah composite key dari semua FK
â Mendominasi ukuran storage data warehouse (80â95%)C.5.2 Tiga Jenis Measures â Penting untuk Agregasi yang Benar!
Ini adalah konsep yang sering diabaikan tapi krusial untuk query analitik yang benar.
1. ADDITIVE MEASURES (Ukuran Aditif)
ââââââââââââââââââââââââââââââââââââ
Definisi: Bisa dijumlahkan (SUM) secara valid di SEMUA dimensi
tanpa menghasilkan angka yang misleading.
Contoh: qty, revenue_bersih, biaya_kirim, jumlah_kunjungan, denda
VALID untuk semua kombinasi:
SUM(revenue_bersih) GROUP BY tahun â â Revenue tahunan
SUM(revenue_bersih) GROUP BY kota â â Revenue per kota
SUM(revenue_bersih) GROUP BY produk â â Revenue per produk
SUM(revenue_bersih) â â Total revenue
â Mayoritas measures yang baik adalah additive
â Jika bisa, desain measures agar additive
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
2. SEMI-ADDITIVE MEASURES (Ukuran Semi-Aditif)
ââââââââââââââââââââââââââââââââââââââââââââââ
Definisi: Bisa dijumlahkan di BEBERAPA dimensi, tapi TIDAK SEMUA.
Biasanya tidak bisa dijumlahkan melewati dimensi WAKTU.
Contoh khas: saldo_rekening, jumlah_stok, jumlah_karyawan_aktif,
nilai_piutang, jumlah_pasien_rawat_inap
ILUSTRASI â saldo_rekening:
SUM(saldo_rekening) GROUP BY bank_id â â Total saldo di bank X
SUM(saldo_rekening) GROUP BY nasabah_id â â Tidak valid!
(menjumlah saldo bulan Jan+Feb+Mar
= bukan total saldo 3 bulan,
tapi angka tidak bermakna)
CARA BENAR untuk dimensi waktu:
â Gunakan AVG untuk rata-rata antar periode
â Gunakan snapshot terbaru (MAX date)
â Contoh: AVG(jumlah_stok) GROUP BY bulan = rata-rata stok bulanan
MAX(saldo) OVER (PARTITION BY bulan) = snapshot akhir bulan
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
3. NON-ADDITIVE MEASURES (Ukuran Non-Aditif)
ââââââââââââââââââââââââââââââââââââââââââââ
Definisi: TIDAK bisa dijumlahkan di dimensi manapun tanpa
menghasilkan angka yang salah.
Contoh: harga_satuan, rasio/persentase, suhu, rating,
nilai_tukar_kurs, margin_persen
ILUSTRASI â harga_satuan:
SUM(harga_satuan) dari 3 baris berbeda â â Tidak bermakna!
(Batik Tulis Rp 600rb + Batik Cap Rp 250rb + Aksesoris Rp 75rb
= Rp 925rb tidak merepresentasikan apapun yang berguna)
CARA BENAR:
â Simpan komponen aditif yang bisa digunakan untuk kalkulasi:
qty (additive) + revenue_bersih (additive)
â harga_rata_rata = SUM(revenue_bersih) / SUM(qty) â BENAR!
â Jangan SUM(harga_satuan) â tapi boleh AVG(harga_satuan) untuk rata-rata
â Simpan harga_satuan di tabel fakta untuk keperluan audit/drill-down,
bukan untuk diagregasi
TABEL RINGKASAN:
ââââââââââââââââââââŦââââââââââââââââââââââââââââââŦââââââââââââââââââââââââââââââââ
â Jenis â Operasi Valid â Contoh â
ââââââââââââââââââââŧââââââââââââââââââââââââââââââŧââââââââââââââââââââââââââââââââ¤
â Additive â SUM di semua dimensi â revenue, qty, biaya, denda â
ââââââââââââââââââââŧââââââââââââââââââââââââââââââŧââââââââââââââââââââââââââââââââ¤
â Semi-additive â SUM di beberapa dimensi, â saldo, stok, jumlah aktif â
â â AVG/snapshot di waktu â â
ââââââââââââââââââââŧââââââââââââââââââââââââââââââŧââââââââââââââââââââââââââââââââ¤
â Non-additive â AVG, atau kalkulasi dari â harga_satuan, rasio, rating â
â â komponen aditif â â
ââââââââââââââââââââ´ââââââââââââââââââââââââââââââ´ââââââââââââââââââââââââââââââââC.5.3 Degenerate Dimension â Dimensi Tanpa Tabel
DEGENERATE DIMENSION adalah atribut yang berperilaku seperti dimensi
(digunakan untuk filter/grouping) tetapi tidak punya tabel dimensi sendiri
karena setelah diekstrak dari tabel OLTP, tidak ada lagi atribut deskriptif
yang tersisa untuk dijadikan tabel terpisah.
CONTOH PALING UMUM: Nomor pesanan (id_pesanan)
id_pesanan di OLTP berisi banyak informasi â JOIN ke tabel pesanan
id_pesanan di DW: setelah semua atribut fakta diambil sebagai measures
dan semua atribut deskriptif diambil ke dimensi, hanya tersisa "nomor"
itu sendiri â tidak punya atribut lain yang berguna di tabel dimensi.
â Simpan id_pesanan LANGSUNG di tabel fakta sebagai degenerate dimension!
â Tidak perlu buat dim_pesanan yang hanya berisi satu kolom nomor.
KAPAN TERJADI:
â Nomor dokumen/transaksi: id_pesanan, nomor_faktur, kode_tiket
â Nomor batch proses: nomor_pengiriman, kode_produksi
CARA IDENTIFIKASI:
Tanya: "Jika saya buat tabel dimensi ini, apakah ada atribut lain
selain natural key-nya? Apakah tabel ini punya nilai deskriptif?"
Jika TIDAK â kandidat degenerate dimension
CONTOH DI FAKTA PENJUALAN TOKO BATIK:
fakta_penjualan:
kunci_waktu FK ke dim_waktu
kunci_pelanggan FK ke dim_pelanggan
kunci_produk FK ke dim_produk
id_pesanan â DEGENERATE DIMENSION (disimpan langsung di fakta)
id_item_pesanan â DEGENERATE DIMENSION
qty, harga_satuan, diskon, revenue_bersih â measures
â id_pesanan berguna untuk: "Tampilkan semua item dalam pesanan #10045"
(drill-through ke detail transaksi)C.6 Materi 4: Tabel Dimensi â Merancang Konteks yang Kaya
C.6.1 Filosofi Dimensi: "Wide, Descriptive, Denormalized"
PRINSIP DESAIN DIMENSI KIMBALL:
"Dimension tables should be wide and short."
(Dimensi harus lebar dan pendek â banyak kolom, sedikit baris)
LEBAR: Banyak atribut deskriptif
â Jangan ragu menambahkan kolom ke dimensi!
â Setiap kolom = satu sudut pandang analitik baru
â Lebih baik terlalu banyak kolom daripada terlalu sedikit
PENDEK: Relatif sedikit baris
â dim_pelanggan: ribuan hingga jutaan baris (vs fakta: ratusan juta)
â dim_produk: ratusan hingga ribuan baris
â dim_waktu: ~3.650 baris (10 tahun) atau ~36.500 baris (100 tahun)
DENORMALIZED (DISENGAJA):
Ini adalah PENYIMPANGAN dari aturan 3NF â dan itu SENGAJA!
OLTP (3NF): redundansi dihindari untuk menjaga integritas DML
DW (dimensi): redundansi diterima untuk mempercepat query SELECT
CONTOH:
OLTP (3NF):
produk(id_produk, nama, id_kategori)
kategori(id_kategori, nama_kategori, id_kategori_induk)
kategori_induk(id_kategori_induk, nama_kategori_induk)
DW (denormalized):
dim_produk(kunci_produk, nama_produk, subkategori, kategori, nama_produk_lengkap,
supplier, asal_kota, rentang_harga, ...)
â Semua atribut hierarki kategori di-flatten ke satu tabel!
â JOIN hanya satu hop dari fakta ke dimensi â jauh lebih cepatC.6.2 Surrogate Key vs Natural Key
SURROGATE KEY: Kunci buatan yang dibuat oleh sistem warehouse
â Biasanya integer auto-increment (1, 2, 3, ...)
â Tidak punya makna bisnis
â WAJIB digunakan sebagai PK di tabel dimensi
MENGAPA SURROGATE KEY DIPERLUKAN:
Alasan 1 â Mendukung SCD Type 2 (dibahas di P13):
Natural key (mis: id_pelanggan) tidak bisa menjadi PK
jika satu pelanggan punya multiple versi historis.
Surrogate key memberi identitas unik pada setiap versi.
Alasan 2 â Independensi dari sumber OLTP:
id_pelanggan di MySQL berbeda dengan customer_id di CRM.
Surrogate key menyatukan keduanya dengan identitas baru.
Alasan 3 â Performa JOIN:
Integer join lebih cepat dari string join
(VARCHAR(50) join >> INT join dari sisi performa)
Alasan 4 â Proteksi dari perubahan sumber:
Jika OLTP mengubah format primary key, warehouse tidak terpengaruh
selama mapping surrogate â natural key di-maintain.
NATURAL KEY: Kunci asli dari sistem sumber OLTP
â Harus TETAP DISIMPAN di dimensi sebagai kolom terpisah
â Digunakan untuk proses ETL (lookup: "apakah record ini sudah ada?")
â Digunakan untuk audit dan penelusuran balik ke sumber
â JANGAN dijadikan PK dimensi di warehouse
KONVENSI PENAMAAN:
kunci_pelanggan â surrogate key (PK dimensi)
id_pelanggan_src â natural key dari sumber (bukan PK)C.6.3 Contoh Dimensi Lengkap
Dimensi Produk â Dari OLTP yang Sederhana ke Dimensi yang Kaya:
TABEL OLTP (3NF):
produk(id_produk, nama_produk, id_kategori, harga_jual, id_supplier)
kategori(id_kategori, nama_kategori, id_kategori_parent)
supplier(id_supplier, nama_supplier, kota_supplier, negara_supplier)
DIMENSI PRODUK DI WAREHOUSE (denormalized, wide):
dim_produk:
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â kunci_produk INT PK, surrogate key (auto-increment) â
â id_produk_src INT natural key dari OLTP â
â nama_produk VARCHAR(200) â
â deskripsi_singkat VARCHAR(500) â
â subkategori VARCHAR(100) â dari tabel kategori (denorm) â
â kategori VARCHAR(100) â kategori induk (denorm) â
â kelompok_kategori VARCHAR(100) â kategori tertinggi (denorm) â
â nama_supplier VARCHAR(150) â dari tabel supplier (denorm) â
â kota_supplier VARCHAR(100) â dari tabel supplier (denorm) â
â asal_produk VARCHAR(100) â 'Lokal' / 'Impor' â
â harga_jual DECIMAL(15,2) â
â rentang_harga VARCHAR(30) â 'Budget'/'Mid'/'Premium' â
â bahan_utama VARCHAR(100) â 'Katun'/'Sutra'/'Sifon' â
â motif VARCHAR(100) â 'Parang'/'Kawung'/'Mega Mendung'â
â teknik_pembuatan VARCHAR(50) â 'Tulis'/'Cap'/'Printing' â
â is_aktif TINYINT(1) â
â berlaku_dari DATE â untuk SCD (dibahas P13) â
â berlaku_sampai DATE â untuk SCD (dibahas P13) â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
PERHATIKAN:
â 19 kolom vs 5 kolom di OLTP â jauh lebih kaya!
â Semua hierarki kategori sudah "di-flatten" â tidak perlu JOIN ke kategori
â Atribut supplier sudah di-embed â tidak perlu JOIN ke supplier
â Kolom turunan (rentang_harga, asal_produk) sudah dikalkulasi saat ETL
â Setiap kolom = satu kemungkinan sudut pandang analitik baruDimensi Pelanggan:
CREATE TABLE dim_pelanggan (
-- SURROGATE KEY
kunci_pelanggan INT UNSIGNED NOT NULL AUTO_INCREMENT,
-- NATURAL KEY dari sumber
id_pelanggan_src INT UNSIGNED NOT NULL,
-- ATRIBUT IDENTITAS
nama_lengkap VARCHAR(150) NOT NULL,
jenis_kelamin CHAR(1) NULL, -- 'L' / 'P'
kelompok_usia VARCHAR(20) NULL, -- 'Remaja', 'Dewasa Muda', 'Dewasa', 'Senior'
rentang_usia VARCHAR(20) NULL, -- '18-24', '25-34', '35-44', ...
-- ATRIBUT LOKASI
kota VARCHAR(100) NOT NULL,
kabupaten_kota VARCHAR(100) NOT NULL,
provinsi VARCHAR(100) NOT NULL,
pulau VARCHAR(50) NOT NULL, -- 'Jawa', 'Sumatera', ...
wilayah VARCHAR(50) NOT NULL, -- 'Jawa Tengah & DIY', 'Jabodetabek', ...
-- ATRIBUT KEANGGOTAAN
tgl_daftar DATE NOT NULL,
tahun_daftar SMALLINT NOT NULL, -- derived dari tgl_daftar
bulan_daftar TINYINT NOT NULL, -- derived dari tgl_daftar
segmen_pelanggan VARCHAR(30) NOT NULL, -- 'Baru', 'Regular', 'Loyal', 'VIP'
lama_keanggotaan_thn SMALLINT NULL, -- berapa tahun sudah menjadi member
-- ATRIBUT HISTORIS (untuk SCD â dibahas P13)
berlaku_dari DATE NOT NULL,
berlaku_sampai DATE NOT NULL DEFAULT '9999-12-31',
is_current TINYINT(1) NOT NULL DEFAULT 1,
CONSTRAINT pk_dim_pelanggan PRIMARY KEY (kunci_pelanggan),
INDEX idx_natural_key (id_pelanggan_src),
INDEX idx_segmen (segmen_pelanggan),
INDEX idx_current (is_current)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Pelanggan â Toko Batik Online DW';C.7 Materi 5: Dimensi Waktu â Fondasi Semua Analitik Temporal
Hampir setiap analisis bisnis memiliki komponen waktu: "bulan ini vs bulan lalu", "tren per kuartal", "perbandingan year-over-year". Karena itu, dim_waktu adalah dimensi yang paling universal dan paling penting dalam hampir semua data warehouse.
C.7.1 Mengapa Dimensi Waktu Spesial
MENGAPA TIDAK CUKUP SIMPAN TANGGAL SAJA DI TABEL FAKTA?
Jika fakta hanya menyimpan: tgl_transaksi DATE
Maka untuk query analitik:
SELECT YEAR(tgl_transaksi), MONTH(tgl_transaksi), SUM(revenue)
FROM fakta_penjualan
GROUP BY YEAR(tgl_transaksi), MONTH(tgl_transaksi);
MASALAH:
â Fungsi YEAR() dan MONTH() dijalankan saat query â untuk jutaan baris!
â Tidak bisa filter dengan mudah "apakah hari ini adalah hari libur nasional?"
â Tidak bisa filter "apakah bulan ini adalah bulan Ramadan?"
â Tidak bisa grouping berdasarkan "semester akademik" atau "musim"
DENGAN dim_waktu yang pre-populated:
SELECT w.tahun, w.nama_bulan, SUM(f.revenue)
FROM fakta_penjualan f
JOIN dim_waktu w ON f.kunci_waktu = w.kunci_waktu
WHERE w.is_hari_libur = 1 -- mudah filter hari libur!
GROUP BY w.tahun, w.nama_bulan;
â Semua kalkulasi temporal sudah dilakukan SEKALI saat populate dim_waktu
â Query lebih bersih, lebih cepat, dan lebih fleksibelC.7.2 DDL Dimensi Waktu Lengkap
-- ============================================================
-- DIMENSI WAKTU â dim_waktu
-- Pre-populated untuk rentang 10 tahun (mis: 2020-2029)
-- Jumlah baris: 3.652 baris (termasuk tahun kabisat)
-- ============================================================
CREATE TABLE dim_waktu (
-- SURROGATE KEY dalam format YYYYMMDD â juga berfungsi sebagai smart key
kunci_waktu INT UNSIGNED NOT NULL, -- e.g. 20240315
-- TANGGAL PENUH
tanggal_penuh DATE NOT NULL,
-- HIERARKI HARI
hari_dalam_bulan TINYINT UNSIGNED NOT NULL, -- 1â31
hari_dalam_tahun SMALLINT UNSIGNED NOT NULL, -- 1â366
nama_hari_en VARCHAR(10) NOT NULL, -- Monday, Tuesday, ...
nama_hari_id VARCHAR(10) NOT NULL, -- Senin, Selasa, ...
nomor_hari_minggu TINYINT UNSIGNED NOT NULL, -- 1=Senin, 7=Minggu (ISO)
is_weekend TINYINT(1) NOT NULL, -- 0=weekday, 1=weekend
is_hari_libur_nas TINYINT(1) NOT NULL DEFAULT 0,
nama_hari_libur VARCHAR(100) NULL, -- 'Hari Raya Idul Fitri 1', dst.
-- HIERARKI MINGGU
minggu_dalam_bulan TINYINT UNSIGNED NOT NULL, -- 1â5
minggu_dalam_tahun TINYINT UNSIGNED NOT NULL, -- 1â53 (ISO week)
minggu_label VARCHAR(20) NOT NULL, -- 'W12 2024'
-- HIERARKI BULAN
bulan TINYINT UNSIGNED NOT NULL, -- 1â12
nama_bulan_en VARCHAR(15) NOT NULL, -- January, February, ...
nama_bulan_id VARCHAR(15) NOT NULL, -- Januari, Februari, ...
nama_bulan_singkat CHAR(3) NOT NULL, -- Jan, Feb, Mar, ...
hari_pertama_bulan DATE NOT NULL,
hari_terakhir_bulan DATE NOT NULL,
jumlah_hari_bulan TINYINT UNSIGNED NOT NULL, -- 28, 29, 30, 31
-- HIERARKI KUARTAL
kuartal TINYINT UNSIGNED NOT NULL, -- 1, 2, 3, 4
nama_kuartal CHAR(2) NOT NULL, -- Q1, Q2, Q3, Q4
hari_pertama_kuartal DATE NOT NULL,
hari_terakhir_kuartal DATE NOT NULL,
-- HIERARKI TAHUN
tahun SMALLINT UNSIGNED NOT NULL, -- 2020, 2021, ...
is_tahun_kabisat TINYINT(1) NOT NULL, -- 0/1
semester TINYINT UNSIGNED NOT NULL, -- 1 atau 2
nama_semester VARCHAR(20) NOT NULL, -- 'Semester 1', 'Semester 2'
tahun_semester VARCHAR(15) NOT NULL, -- '2024/1', '2024/2'
-- ATRIBUT KHUSUS BISNIS (dapat dikustomisasi)
is_bulan_puasa TINYINT(1) NOT NULL DEFAULT 0,
nama_musim VARCHAR(20) NULL, -- 'Kemarau', 'Hujan'
periode_fiskal VARCHAR(20) NULL, -- untuk tahun fiskal berbeda
label_relatif VARCHAR(30) NULL, -- 'Bulan Ini', 'Bulan Lalu', dll.
CONSTRAINT pk_dim_waktu PRIMARY KEY (kunci_waktu),
INDEX idx_tanggal (tanggal_penuh),
INDEX idx_bulan_tahun (tahun, bulan),
INDEX idx_kuartal_tahun (tahun, kuartal),
INDEX idx_hari_libur (is_hari_libur_nas)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Waktu â pre-populated untuk periode analisis';C.7.3 Cara Mengisi (Populate) Dimensi Waktu
-- Prosedur sederhana untuk populate dim_waktu
-- Mengisi satu tahun tertentu (contoh: 2024)
-- Dalam praktik, jalankan untuk semua tahun yang diperlukan
DELIMITER //
CREATE PROCEDURE populate_dim_waktu(p_tahun SMALLINT)
BEGIN
DECLARE v_tanggal DATE;
DECLARE v_akhir_tahun DATE;
SET v_tanggal = MAKEDATE(p_tahun, 1); -- 1 Januari tahun p_tahun
SET v_akhir_tahun = MAKEDATE(p_tahun + 1, 1) - INTERVAL 1 DAY; -- 31 Des
WHILE v_tanggal <= v_akhir_tahun DO
INSERT INTO dim_waktu (
kunci_waktu,
tanggal_penuh,
hari_dalam_bulan,
hari_dalam_tahun,
nama_hari_en,
nama_hari_id,
nomor_hari_minggu,
is_weekend,
minggu_dalam_tahun,
minggu_label,
bulan,
nama_bulan_en,
nama_bulan_id,
nama_bulan_singkat,
hari_pertama_bulan,
hari_terakhir_bulan,
jumlah_hari_bulan,
minggu_dalam_bulan,
kuartal,
nama_kuartal,
hari_pertama_kuartal,
hari_terakhir_kuartal,
tahun,
is_tahun_kabisat,
semester,
nama_semester,
tahun_semester
) VALUES (
DATE_FORMAT(v_tanggal, '%Y%m%d') + 0, -- YYYYMMDD sebagai INT
v_tanggal,
DAY(v_tanggal),
DAYOFYEAR(v_tanggal),
DAYNAME(v_tanggal), -- English day name
ELT(DAYOFWEEK(v_tanggal), 'Minggu','Senin','Selasa','Rabu',
'Kamis','Jumat','Sabtu'), -- Indonesia day name
-- ISO: Senin=1 ... Minggu=7
CASE DAYOFWEEK(v_tanggal)
WHEN 1 THEN 7 ELSE DAYOFWEEK(v_tanggal) - 1 END,
IF(DAYOFWEEK(v_tanggal) IN (1,7), 1, 0), -- is_weekend
WEEK(v_tanggal, 3), -- ISO week number
CONCAT('W', LPAD(WEEK(v_tanggal,3),2,'0'), ' ', YEAR(v_tanggal)),
MONTH(v_tanggal),
MONTHNAME(v_tanggal),
ELT(MONTH(v_tanggal),'Januari','Februari','Maret','April','Mei',
'Juni','Juli','Agustus','September','Oktober','November','Desember'),
LEFT(MONTHNAME(v_tanggal), 3),
DATE_FORMAT(v_tanggal, '%Y-%m-01'),
LAST_DAY(v_tanggal),
DAY(LAST_DAY(v_tanggal)),
CEIL(DAY(v_tanggal)/7.0),
CEIL(MONTH(v_tanggal)/3.0),
CONCAT('Q', CEIL(MONTH(v_tanggal)/3.0)),
MAKEDATE(YEAR(v_tanggal), (CEIL(MONTH(v_tanggal)/3.0)-1)*91+1),
LAST_DAY(DATE_ADD(MAKEDATE(YEAR(v_tanggal),
(CEIL(MONTH(v_tanggal)/3.0))*3-0,1)-INTERVAL 1 DAY)),
YEAR(v_tanggal),
IF(YEAR(v_tanggal) % 4 = 0 AND (YEAR(v_tanggal)%100 != 0
OR YEAR(v_tanggal)%400 = 0), 1, 0),
IF(MONTH(v_tanggal) <= 6, 1, 2),
IF(MONTH(v_tanggal) <= 6, 'Semester 1', 'Semester 2'),
CONCAT(YEAR(v_tanggal), '/', IF(MONTH(v_tanggal) <= 6, 1, 2))
);
SET v_tanggal = v_tanggal + INTERVAL 1 DAY;
END WHILE;
END //
DELIMITER ;
-- Jalankan untuk mengisi:
CALL populate_dim_waktu(2022);
CALL populate_dim_waktu(2023);
CALL populate_dim_waktu(2024);
CALL populate_dim_waktu(2025);C.8 Materi 6: Variasi Dimensi Khusus
C.8.1 Conformed Dimension (Dimensi yang Dikondisikan/Dikondisikan)
DEFINISI:
Dimensi yang SAMA (identik atau kompatibel) digunakan oleh
BEBERAPA tabel fakta berbeda dalam data warehouse.
ANALOGINYA:
dim_pelanggan yang sama dipakai oleh:
â fakta_penjualan (pelanggan beli produk)
â fakta_retur (pelanggan retur produk)
â fakta_interaksi_cs (pelanggan hubungi customer service)
â fakta_ulasan (pelanggan beri ulasan)
â Semua tabel fakta ini "berbicara" tentang pelanggan yang SAMA,
dengan definisi yang SAMA, dengan surrogate key yang SAMA!
MANFAAT:
â Bisa JOIN atau UNION antar tabel fakta melalui dimensi yang sama
â Definisi "pelanggan" konsisten di seluruh laporan
â "Drill across": lihat perilaku satu pelanggan dari berbagai proses
CONTOH DRILL ACROSS (menggabungkan dua tabel fakta):
-- Berapa pelanggan yang beli tapi tidak pernah retur?
SELECT p.nama_lengkap, SUM(f.revenue_bersih) AS total_belanja
FROM fakta_penjualan f
JOIN dim_pelanggan p ON f.kunci_pelanggan = p.kunci_pelanggan
WHERE NOT EXISTS (
SELECT 1 FROM fakta_retur r
WHERE r.kunci_pelanggan = p.kunci_pelanggan
)
GROUP BY p.kunci_pelanggan, p.nama_lengkap;C.8.2 Role-Playing Dimension (Dimensi Satu Peran Banyak)
DEFINISI:
Satu tabel dimensi yang digunakan BEBERAPA KALI dalam satu tabel fakta,
masing-masing dengan peran (role) yang berbeda.
CONTOH PALING UMUM â dim_waktu dipakai berkali-kali:
Sistem logistik pengiriman:
fakta_pengiriman:
kunci_waktu_pesan â dim_waktu (tanggal pesanan dibuat)
kunci_waktu_kirim â dim_waktu (tanggal paket dikirim)
kunci_waktu_terima â dim_waktu (tanggal paket diterima)
kunci_waktu_retur â dim_waktu (tanggal retur jika ada)
â Keempat FK semua merujuk ke DIM_WAKTU yang SAMA!
â Tapi masing-masing memiliki makna/peran yang berbeda
CARA IMPLEMENTASI â menggunakan VIEW (alias):
-- Buat alias view untuk setiap peran
CREATE VIEW dim_waktu_pesan AS SELECT * FROM dim_waktu;
CREATE VIEW dim_waktu_kirim AS SELECT * FROM dim_waktu;
CREATE VIEW dim_waktu_terima AS SELECT * FROM dim_waktu;
-- Query menggunakan alias view:
SELECT
w_pesan.tahun AS tahun_pesanan,
w_pesan.nama_bulan_id AS bulan_pesanan,
w_terima.tahun AS tahun_terima,
DATEDIFF(f.kunci_waktu_terima, f.kunci_waktu_kirim) AS hari_kirim
FROM fakta_pengiriman f
JOIN dim_waktu_pesan w_pesan ON f.kunci_waktu_pesan = w_pesan.kunci_waktu
JOIN dim_waktu_terima w_terima ON f.kunci_waktu_terima = w_terima.kunci_waktu;C.8.3 Junk Dimension (Dimensi Sampah)
DEFINISI:
Dimensi yang menggabungkan beberapa atribut flag/status berkardinasi rendah
yang tidak cukup penting untuk menjadi dimensi tersendiri, tapi tidak
elegan jika diletakkan langsung di tabel fakta.
MASALAH YANG DISELESAIKAN:
Tabel fakta penjualan punya banyak flag kecil:
is_transaksi_web, is_member, is_promo, is_bayar_dp, is_pengiriman_express
Jika diletakkan di tabel fakta â 5 kolom tambahan yang membuat fakta "gemuk"
Jika buat 5 dimensi terpisah â overhead JOIN yang tidak perlu
SOLUSI â Gabungkan ke SATU "junk dimension":
dim_tipe_transaksi:
âââââââââââââââââââââŦâââââââââââââââŦââââââââââââŦâââââââââââââŦââââââââââââââââââââ
â kunci_tipe_trans â via_web â is_member â ada_promo â is_express â
âââââââââââââââââââââŧâââââââââââââââŧââââââââââââŧâââââââââââââŧââââââââââââââââââââ¤
â 1 â 1 â 1 â 1 â 1 â
â 2 â 1 â 1 â 1 â 0 â
â 3 â 1 â 1 â 0 â 1 â
â 4 â 1 â 1 â 0 â 0 â
â 5 â 1 â 0 â 1 â 1 â
â ... â ... â ... â ... â ... â
â 16 â 0 â 0 â 0 â 0 â
âââââââââââââââââââââ´âââââââââââââââ´ââââââââââââ´âââââââââââââ´ââââââââââââââââââââ
â 4 flag boolean = 2^4 = 16 kombinasi â 16 baris di dim_tipe_transaksi
â Tabel fakta hanya butuh satu FK: kunci_tipe_trans
â Analisis tetap bisa dilakukan: WHERE dim_tipe_trans.is_member = 1C.9 Implementasi Lengkap: Star Schema Toko Batik Online
Sekarang kita wujudkan semua konsep di atas menjadi DDL yang lengkap dan siap dijalankan.
C.9.1 Diagram Star Schema
ââââââââââââââââââââ
â dim_waktu â
â âââââââââââââââ â
â kunci_waktu PK â
â tanggal_penuh â
â tahun â
â nama_bulan_id â
â kuartal â
â is_weekend â
â ... (30+ kolom) â
ââââââââââŦââââââââââ
â
ââââââââââââââââ â ââââââââââââââââââââ
â dim_pelangganâ â â dim_produk â
â ââââââââââââ â â â ââââââââââââââââ â
â kunci_pel. PKâ â â kunci_produk PK â
â nama_lengkap â â â nama_produk â
â kota â â â kategori â
â provinsi â â â subkategori â
â segmen â â â teknik_pembuatan â
â kelompok_usiaâ â â rentang_harga â
â ... â â â ... â
ââââââââŦââââââââ â ââââââââââŦââââââââââ
â â â
ââââââââââââââââââŧââââââââââââââââââ
â
âââââââââââââââŧâââââââââââââââââââ
â FAKTA_PENJUALAN â
â âââââââââââââââââââââââââââââ â
â kunci_waktu FK â
â kunci_pelanggan FK â
â kunci_produk FK â
â kunci_lokasi_kirim FK â
â kunci_kanal FK â
â id_pesanan (degen.) â
â id_item_pesanan (degen.) â
â âââââââââââââââââââââââââââââ â
â qty measure â
â harga_satuan measure â
â diskon measure â
â revenue_bersih measure â
â biaya_kirim measure â
âââââââââââŦâââââââââââââââââââââââ
â
ââââââââââââââââ´âââââââââââââââ
â â
ââââââââââââŧâââââââââ ââââââââââââŧâââââââââââ
â dim_lokasi_kirim â â dim_kanal â
â ââââââââââââââââ â â ââââââââââââââââââ â
â kunci_lokasi PKâ â kunci_kanal PKâ
â kota_kirim â â nama_kanal â
â kabupaten_kota â â tipe_kanal â
â provinsi_kirim â â platform â
â pulau â â is_online â
â zona_pengiriman â â â
âââââââââââââââââââââ âââââââââââââââââââââââC.9.2 DDL Lengkap â Seluruh Star Schema
-- ============================================================
-- DATABASE WAREHOUSE TOKO BATIK ONLINE
-- Star Schema â Proses Bisnis: Penjualan
-- Dibuat untuk: Data Modelling MK â Pertemuan 12
-- ============================================================
-- Buat database warehouse (terpisah dari database OLTP)
CREATE DATABASE IF NOT EXISTS dw_batik_online
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
USE dw_batik_online;
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- TABEL DIMENSI (harus dibuat SEBELUM tabel fakta)
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- 1. DIMENSI WAKTU
CREATE TABLE dim_waktu (
kunci_waktu INT UNSIGNED NOT NULL, -- Format YYYYMMDD
tanggal_penuh DATE NOT NULL,
hari_dalam_bulan TINYINT UNSIGNED NOT NULL,
hari_dalam_tahun SMALLINT UNSIGNED NOT NULL,
nama_hari_en VARCHAR(10) NOT NULL,
nama_hari_id VARCHAR(10) NOT NULL,
nomor_hari_minggu TINYINT UNSIGNED NOT NULL, -- ISO: Sen=1 Min=7
is_weekend TINYINT(1) NOT NULL DEFAULT 0,
is_hari_libur_nas TINYINT(1) NOT NULL DEFAULT 0,
nama_hari_libur VARCHAR(100) NULL,
minggu_dalam_tahun TINYINT UNSIGNED NOT NULL,
bulan TINYINT UNSIGNED NOT NULL,
nama_bulan_id VARCHAR(15) NOT NULL,
nama_bulan_singkat CHAR(3) NOT NULL,
kuartal TINYINT UNSIGNED NOT NULL,
nama_kuartal CHAR(2) NOT NULL,
semester TINYINT UNSIGNED NOT NULL,
tahun SMALLINT UNSIGNED NOT NULL,
is_tahun_kabisat TINYINT(1) NOT NULL DEFAULT 0,
tahun_semester VARCHAR(15) NOT NULL,
CONSTRAINT pk_dim_waktu PRIMARY KEY (kunci_waktu),
INDEX idx_tgl (tanggal_penuh),
INDEX idx_tahun_bulan (tahun, bulan),
INDEX idx_tahun_kuartal (tahun, kuartal)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Waktu â pre-populated';
-- 2. DIMENSI PELANGGAN
CREATE TABLE dim_pelanggan (
kunci_pelanggan INT UNSIGNED NOT NULL AUTO_INCREMENT,
id_pelanggan_src INT UNSIGNED NOT NULL, -- natural key dari OLTP
nama_lengkap VARCHAR(150) NOT NULL,
jenis_kelamin CHAR(1) NULL, -- 'L'/'P'
kelompok_usia VARCHAR(20) NULL,
kota VARCHAR(100) NOT NULL,
kabupaten_kota VARCHAR(100) NOT NULL,
provinsi VARCHAR(100) NOT NULL,
pulau VARCHAR(50) NOT NULL,
wilayah VARCHAR(50) NOT NULL,
tgl_daftar DATE NOT NULL,
tahun_daftar SMALLINT NOT NULL,
segmen_pelanggan VARCHAR(30) NOT NULL DEFAULT 'Baru',
-- Kolom SCD Type 2 (dibahas detail di Pertemuan 13)
berlaku_dari DATE NOT NULL,
berlaku_sampai DATE NOT NULL DEFAULT '9999-12-31',
is_current TINYINT(1) NOT NULL DEFAULT 1,
CONSTRAINT pk_dim_pelanggan PRIMARY KEY (kunci_pelanggan),
INDEX idx_natural_key_pel (id_pelanggan_src),
INDEX idx_segmen (segmen_pelanggan),
INDEX idx_current_pel (is_current)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Pelanggan â dengan kolom SCD untuk P13';
-- 3. DIMENSI PRODUK
CREATE TABLE dim_produk (
kunci_produk INT UNSIGNED NOT NULL AUTO_INCREMENT,
id_produk_src INT UNSIGNED NOT NULL, -- natural key dari OLTP
nama_produk VARCHAR(200) NOT NULL,
subkategori VARCHAR(100) NOT NULL,
kategori VARCHAR(100) NOT NULL,
kelompok_kategori VARCHAR(100) NOT NULL,
nama_supplier VARCHAR(150) NOT NULL,
kota_supplier VARCHAR(100) NOT NULL,
asal_produk VARCHAR(30) NOT NULL DEFAULT 'Lokal',
harga_jual DECIMAL(15,2) NOT NULL,
rentang_harga VARCHAR(30) NOT NULL, -- 'Budget'/'Mid'/'Premium'
bahan_utama VARCHAR(100) NULL,
motif VARCHAR(100) NULL,
teknik_pembuatan VARCHAR(50) NULL, -- 'Tulis'/'Cap'/'Printing'
is_aktif TINYINT(1) NOT NULL DEFAULT 1,
-- Kolom SCD
berlaku_dari DATE NOT NULL,
berlaku_sampai DATE NOT NULL DEFAULT '9999-12-31',
is_current TINYINT(1) NOT NULL DEFAULT 1,
CONSTRAINT pk_dim_produk PRIMARY KEY (kunci_produk),
INDEX idx_natural_key_prod (id_produk_src),
INDEX idx_kategori (kategori),
INDEX idx_teknik (teknik_pembuatan),
INDEX idx_current_prod (is_current)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Produk â denormalized dari OLTP';
-- 4. DIMENSI LOKASI PENGIRIMAN
CREATE TABLE dim_lokasi_kirim (
kunci_lokasi INT UNSIGNED NOT NULL AUTO_INCREMENT,
kota_kirim VARCHAR(100) NOT NULL,
kabupaten_kota VARCHAR(100) NOT NULL,
provinsi_kirim VARCHAR(100) NOT NULL,
pulau VARCHAR(50) NOT NULL,
wilayah_kirim VARCHAR(50) NOT NULL, -- 'Jabodetabek', 'Jawa Tengah', dll.
zona_pengiriman VARCHAR(20) NOT NULL, -- 'Zona 1', 'Zona 2', 'Zona 3'
estimasi_hari_kirim TINYINT NOT NULL, -- estimasi hari pengiriman reguler
CONSTRAINT pk_dim_lokasi PRIMARY KEY (kunci_lokasi),
INDEX idx_provinsi (provinsi_kirim),
UNIQUE INDEX idx_kota_prov (kota_kirim, provinsi_kirim)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Lokasi Pengiriman';
-- 5. DIMENSI KANAL PENJUALAN
CREATE TABLE dim_kanal (
kunci_kanal TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
nama_kanal VARCHAR(100) NOT NULL, -- 'Website', 'Tokopedia', dst.
tipe_kanal VARCHAR(50) NOT NULL, -- 'Marketplace', 'Direct', 'Sosmed'
platform VARCHAR(50) NOT NULL, -- 'Web', 'Mobile App', 'Offline'
is_online TINYINT(1) NOT NULL DEFAULT 1,
CONSTRAINT pk_dim_kanal PRIMARY KEY (kunci_kanal)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Dimensi Kanal Penjualan';
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- TABEL FAKTA
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- FAKTA PENJUALAN
-- Grain: Satu baris = satu item baris (line item) dalam satu pesanan
-- Setiap baris = "Pada tanggal X, Pelanggan Y membeli Produk Z via Kanal K
-- ke Kota L, sebanyak qty unit, dengan harga P, diskon D"
CREATE TABLE fakta_penjualan (
-- KUNCI ASING ke DIMENSI
kunci_waktu INT UNSIGNED NOT NULL,
kunci_pelanggan INT UNSIGNED NOT NULL,
kunci_produk INT UNSIGNED NOT NULL,
kunci_lokasi INT UNSIGNED NOT NULL,
kunci_kanal TINYINT UNSIGNED NOT NULL,
-- DEGENERATE DIMENSIONS (no separate dimension table)
id_pesanan INT UNSIGNED NOT NULL, -- no. pesanan dari OLTP
id_item_pesanan INT UNSIGNED NOT NULL, -- no. baris item dari OLTP
-- MEASURES
qty SMALLINT UNSIGNED NOT NULL DEFAULT 1, -- additive
harga_satuan DECIMAL(15,2) NOT NULL, -- non-additive
diskon DECIMAL(15,2) NOT NULL DEFAULT 0.00,-- additive
revenue_bersih DECIMAL(15,2) NOT NULL, -- additive
biaya_kirim DECIMAL(15,2) NOT NULL DEFAULT 0.00,-- additive (per item)
hpp_satuan DECIMAL(15,2) NULL, -- non-additive (harga pokok)
laba_kotor DECIMAL(15,2) NULL, -- additive
-- PRIMARY KEY (composite)
CONSTRAINT pk_fakta_penjualan
PRIMARY KEY (kunci_waktu, kunci_pelanggan, kunci_produk,
id_pesanan, id_item_pesanan),
-- FOREIGN KEYS ke dimensi
CONSTRAINT fk_fp_waktu
FOREIGN KEY (kunci_waktu) REFERENCES dim_waktu (kunci_waktu),
CONSTRAINT fk_fp_pelanggan
FOREIGN KEY (kunci_pelanggan) REFERENCES dim_pelanggan (kunci_pelanggan),
CONSTRAINT fk_fp_produk
FOREIGN KEY (kunci_produk) REFERENCES dim_produk (kunci_produk),
CONSTRAINT fk_fp_lokasi
FOREIGN KEY (kunci_lokasi) REFERENCES dim_lokasi_kirim (kunci_lokasi),
CONSTRAINT fk_fp_kanal
FOREIGN KEY (kunci_kanal) REFERENCES dim_kanal (kunci_kanal),
-- INDEX tambahan untuk performa query umum
INDEX idx_fp_waktu_produk (kunci_waktu, kunci_produk),
INDEX idx_fp_waktu_pelanggan (kunci_waktu, kunci_pelanggan),
INDEX idx_fp_pesanan (id_pesanan)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Fakta Penjualan â Grain: satu baris per item pesanan';C.9.3 Query Analitik Demonstrasi
-- ============================================================
-- QUERY ANALITIK â Demonstrasi kekuatan star schema
-- Semua query ini berlari jauh lebih cepat daripada di OLTP
-- ============================================================
-- Query 1: Revenue per Kategori per Bulan (laporan paling umum)
SELECT
w.tahun,
w.nama_bulan_id,
w.bulan,
p.kategori,
SUM(f.revenue_bersih) AS total_revenue,
SUM(f.qty) AS total_unit_terjual,
COUNT(DISTINCT f.id_pesanan) AS jumlah_pesanan
FROM fakta_penjualan f
JOIN dim_waktu w ON f.kunci_waktu = w.kunci_waktu
JOIN dim_produk p ON f.kunci_produk = p.kunci_produk
WHERE w.tahun = 2024
GROUP BY w.tahun, w.bulan, w.nama_bulan_id, p.kategori
ORDER BY w.bulan, total_revenue DESC;
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- Query 2: Analisis Year-Over-Year (YoY) Revenue per Produk
SELECT
p.nama_produk,
p.kategori,
SUM(CASE WHEN w.tahun = 2023 THEN f.revenue_bersih ELSE 0 END) AS revenue_2023,
SUM(CASE WHEN w.tahun = 2024 THEN f.revenue_bersih ELSE 0 END) AS revenue_2024,
ROUND(
(SUM(CASE WHEN w.tahun = 2024 THEN f.revenue_bersih ELSE 0 END)
- SUM(CASE WHEN w.tahun = 2023 THEN f.revenue_bersih ELSE 0 END))
/ NULLIF(SUM(CASE WHEN w.tahun = 2023 THEN f.revenue_bersih ELSE 0 END), 0)
* 100, 2
) AS pct_pertumbuhan_yoy
FROM fakta_penjualan f
JOIN dim_waktu w ON f.kunci_waktu = w.kunci_waktu
JOIN dim_produk p ON f.kunci_produk = p.kunci_produk
WHERE w.tahun IN (2023, 2024)
GROUP BY p.kunci_produk, p.nama_produk, p.kategori
HAVING revenue_2023 > 0
ORDER BY pct_pertumbuhan_yoy DESC
LIMIT 20;
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- Query 3: Segmentasi Pelanggan â RFM Sederhana (Recency, Frequency, Monetary)
SELECT
pel.segmen_pelanggan,
COUNT(DISTINCT f.kunci_pelanggan) AS jumlah_pelanggan,
ROUND(AVG(rev_per_pelanggan.total_revenue), 0) AS avg_revenue_per_pelanggan,
ROUND(AVG(freq_per_pelanggan.jumlah_pesanan), 1) AS avg_frekuensi_pesanan
FROM dim_pelanggan pel
JOIN (
SELECT kunci_pelanggan, SUM(revenue_bersih) AS total_revenue
FROM fakta_penjualan
GROUP BY kunci_pelanggan
) rev_per_pelanggan ON pel.kunci_pelanggan = rev_per_pelanggan.kunci_pelanggan
JOIN (
SELECT kunci_pelanggan, COUNT(DISTINCT id_pesanan) AS jumlah_pesanan
FROM fakta_penjualan
GROUP BY kunci_pelanggan
) freq_per_pelanggan ON pel.kunci_pelanggan = freq_per_pelanggan.kunci_pelanggan
JOIN fakta_penjualan f ON pel.kunci_pelanggan = f.kunci_pelanggan
WHERE pel.is_current = 1
GROUP BY pel.segmen_pelanggan
ORDER BY avg_revenue_per_pelanggan DESC;
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- Query 4: Analisis Pola Waktu â Weekday vs Weekend dan Hari Libur
SELECT
CASE
WHEN w.is_hari_libur_nas = 1 THEN 'Hari Libur Nasional'
WHEN w.is_weekend = 1 THEN 'Weekend'
ELSE 'Hari Kerja'
END AS tipe_hari,
COUNT(DISTINCT f.id_pesanan) AS jumlah_pesanan,
SUM(f.revenue_bersih) AS total_revenue,
ROUND(AVG(f.revenue_bersih), 0) AS avg_revenue_per_item,
ROUND(SUM(f.revenue_bersih) / COUNT(DISTINCT f.id_pesanan), 0)
AS avg_revenue_per_pesanan
FROM fakta_penjualan f
JOIN dim_waktu w ON f.kunci_waktu = w.kunci_waktu
WHERE w.tahun = 2024
GROUP BY tipe_hari
ORDER BY total_revenue DESC;
-- ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-- Query 5: Top 10 Kota Pengiriman berdasarkan Revenue (Drill-down ke Provinsi)
SELECT
l.provinsi_kirim,
l.kota_kirim,
COUNT(DISTINCT f.kunci_pelanggan) AS jumlah_pelanggan_unik,
SUM(f.revenue_bersih) AS total_revenue,
SUM(f.qty) AS total_unit,
ROUND(SUM(f.revenue_bersih) / COUNT(DISTINCT f.kunci_pelanggan), 0) AS revenue_per_pelanggan
FROM fakta_penjualan f
JOIN dim_lokasi_kirim l ON f.kunci_lokasi = l.kunci_lokasi
JOIN dim_waktu w ON f.kunci_waktu = w.kunci_waktu
WHERE w.tahun = 2024
GROUP BY l.provinsi_kirim, l.kota_kirim
ORDER BY total_revenue DESC
LIMIT 10;D. LATIHAN DAN DISKUSI
D.1 Latihan Individual: Empat Langkah untuk Domain Baru (10 menit)
Instruksi: Terapkan Kimball's Four-Step Process untuk proses bisnis berikut.
Skenario: Sebuah rumah sakit ingin membangun data mart untuk menganalisis kunjungan pasien rawat jalan. Saat ini sistem OLTP memiliki tabel: pasien, dokter, poli, jadwal_praktek, kunjungan, diagnosis, resep, obat.
Tugas (kerjakan di kertas):
Langkah 1 â Proses Bisnis: Tuliskan proses bisnis yang paling tepat untuk dimodelkan. Jelaskan mengapa kamu memilihnya.
Langkah 2 â Grain: Tuliskan grain dalam satu kalimat yang jelas. Pertimbangkan: apakah "satu baris per kunjungan" cukup? Atau perlu per layanan per kunjungan?
Langkah 3 â Dimensi: Daftarkan minimal 5 dimensi. Untuk setiap dimensi, tuliskan 3â5 atribut yang akan disertakan.
Langkah 4 â Measures: Daftarkan minimal 5 measures. Tentukan tipe (additive/semi-additive/non-additive) dan jelaskan alasannya.
D.2 Praktikum Kelompok: Rancang Star Schema untuk Domain Proyek! (20 menit)
Ini adalah praktikum paling penting di pertemuan ini â langsung berkaitan dengan tugas proyek akhir!
Instruksi: Setiap kelompok menggunakan domain proyek mereka sendiri (yang sudah dirancang OLTP-nya di Pertemuan 9). Rancang star schema untuk satu proses bisnis utama dari domain tersebut.
Output yang harus dihasilkan (di kertas atau draw.io):
- Deklarasi grain â satu kalimat spesifik
- Daftar dimensi â nama, minimal 6 atribut per dimensi
- Tabel fakta â nama, semua FK, semua measures + tipe measures
- Diagram star schema â gambar sederhana menunjukkan tabel dan relasi
- 2 contoh pertanyaan analitik yang bisa dijawab dengan schema ini
Panduan untuk masing-masing domain proyek:
| Domain | Proses Bisnis Disarankan | Hint Grain |
|---|---|---|
| Perpustakaan | Peminjaman buku | Satu baris per buku per transaksi peminjaman |
| Klinik/Puskesmas | Kunjungan pasien | Satu baris per kunjungan pasien |
| UMKM/Toko | Penjualan produk | Satu baris per item baris (line item) pesanan |
| Kampus/Akademik | Pengambilan MK | Satu baris per mahasiswa per MK per semester |
| Hotel/Penginapan | Pemesanan kamar | Satu baris per malam per kamar per pemesanan |
| Restoran | Pesanan makanan | Satu baris per item menu per pesanan |
| Event/Tiket | Penjualan tiket | Satu baris per tiket per acara |
Presentasi singkat: 2â3 menit per kelompok, tunjukkan diagram dan deklarasi grain.
D.3 Diskusi: Anti-Pattern dalam Star Schema (5 menit)
Dosen membahas kesalahan umum yang sering terjadi saat merancang star schema pertama kali:
ANTI-PATTERN 1: Grain yang Tidak Konsisten
â Salah: Satu tabel fakta berisi baris dengan grain berbeda
(sebagian per pesanan, sebagian per item)
â Benar: Satu grain yang jelas dan konsisten di seluruh tabel
ANTI-PATTERN 2: Memasukkan Data Deskriptif ke Tabel Fakta
â Salah: fakta_penjualan berisi nama_pelanggan, nama_produk, kota
â Benar: Data deskriptif masuk ke dimensi, fakta hanya FK dan measures
ANTI-PATTERN 3: Normalisasi Dimensi (Snowflake tanpa tujuan)
â Salah: dim_produk punya FK ke dim_kategori punya FK ke dim_kategori_induk
â Benar: dim_produk memiliki kolom subkategori, kategori, kelompok_kategori
(semua di-flatten dalam satu tabel)
ANTI-PATTERN 4: Lupa Menyertakan Natural Key di Dimensi
â Salah: dim_pelanggan hanya punya kunci_pelanggan (surrogate), tanpa id asli
â Benar: dim_pelanggan punya kunci_pelanggan (PK) DAN id_pelanggan_src
ANTI-PATTERN 5: Grain Terlalu Tinggi / Pre-Aggregated Grain
â Salah: "Satu baris per bulan per produk" (sudah aggregate)
â Benar: "Satu baris per transaksi" â agregasi dilakukan oleh query,
bukan oleh desain grainD.4 Latihan Cepatl: Grain Consistency Verification (5 menit)
Tujuan: Melatih kemampuan mendeteksi inkonsistensi grain dalam satu tabel fakta. Ini adalah keterampilan kritis yang sering bernilai dalam peer-review desain DW.
Instruksi: Perhatikan masing-masing tabel fakta berikut. Identifikasi apakah grain-nya konsisten atau tidak, dan jelaskan alasannya.
Kasus A â fakta_penjualan_online:
| Kolom | Keterangan |
|---|---|
| kunci_waktu | Tanggal transaksi |
| kunci_pelanggan | Pelanggan |
| kunci_produk | Produk |
| kunci_kurir | Perusahaan pengiriman |
| qty | Jumlah item |
| subtotal | Harga x qty |
| total_pesanan | Total seluruh pesanan (semua item) |
| biaya_kirim | Biaya kirim seluruh pesanan |
Apakah grain-nya konsisten? Grain yang dideklarasikan adalah "satu baris per item produk per pesanan".
Kasus B â fakta_kunjungan_rs:
| Kolom | Keterangan |
|---|---|
| kunci_waktu | Tanggal kunjungan |
| kunci_pasien | Pasien |
| kunci_dokter | Dokter yang menangani |
| kunci_poli | Poli kunjungan |
| durasi_konsultasi_menit | Lama konsultasi |
| biaya_konsultasi | Biaya konsultasi |
| jumlah_item_resep | Jumlah obat yang diresepkan |
Apakah grain-nya konsisten? Grain yang dideklarasikan adalah "satu baris per kunjungan pasien ke satu poli".
E. EVALUASI DAN PENILAIAN
E.1 Kuis Penutup (10 menit, bobot partisipasi)
-
Sebutkan empat langkah Kimball's Four-Step Process secara berurutan. Mengapa urutan ini penting?
-
Sebuah data engineer mengusulkan grain: "Satu baris per pelanggan per bulan yang berisi total belanja bulan tersebut." Apa masalah dari grain ini? Bagaimana kamu memperbaikinya?
-
Di tabel fakta pemesanan hotel, terdapat kolom
rating_kepuasan(skala 1â5). Apakah ini additive, semi-additive, atau non-additive? Jelaskan dan tunjukkan cara yang benar untuk menggunakannya dalam query analitik! -
Apa itu surrogate key dan mengapa ia wajib digunakan di tabel dimensi? Sebutkan minimal 2 alasan!
-
Dalam star schema sistem perpustakaan,
id_peminjaman(nomor transaksi) tidak memiliki atribut deskriptif tambahan yang perlu disimpan di dimensi tersendiri. Apa istilah untuk ini dan bagaimana cara menyimpannya di skema?
E.2 Tugas Proyek: Rancang dan Implementasikan Star Schema Kelompok
Judul: Perancangan Star Schema untuk Domain Proyek
Deskripsi: Kelompok merancang dan mengimplementasikan star schema untuk satu proses bisnis utama dari domain proyek mereka. Ini adalah Tahap 7 (Dimensional Model) dari proyek bertahap semester ini.
Deliverables â Bagian 1: Dokumen Perancangan (PDF)
Bagian 1.1 â Deklarasi Desain (1 halaman)
- Proses bisnis yang dimodelkan
- Pernyataan grain (satu kalimat spesifik)
- Justifikasi grain: mengapa granularitas ini dipilih? Apa yang hilang jika terlalu tinggi? Apa yang berlebihan jika terlalu rendah?
Bagian 1.2 â Dimensi (1â2 halaman)
- Untuk setiap dimensi: nama tabel, surrogate key, natural key, dan daftar semua kolom beserta tipe data
- Jelaskan atribut-atribut turunan (derived attributes) yang ditambahkan saat ETL
- Identifikasi dimensi mana yang conformed (bisa digunakan bersama oleh proses bisnis lain)
Bagian 1.3 â Tabel Fakta (0.5 halaman)
- Daftar semua kolom (FK, degenerate dimensions, measures)
- Untuk setiap measure: tipe (additive/semi-additive/non-additive) dan penjelasan
- Composite PK yang digunakan
Bagian 1.4 â Diagram Star Schema
- Diagram visual yang menunjukkan semua tabel dan relasi FK
- Gunakan Draw.io atau MySQL Workbench untuk star schema diagram (rekomendasi: Draw.io untuk visual clarity)
Bagian 1.5 â Pertanyaan Analitik (0.5 halaman)
- 5 pertanyaan analitik yang bisa dijawab oleh star schema ini
- Untuk setiap pertanyaan: tuliskan dimensi dan measure yang digunakan
Deliverables â Bagian 2: Implementasi SQL (file .sql)
File SQL harus berisi:
- DDL lengkap seluruh tabel dimensi (minimal 4 dimensi)
- DDL tabel fakta beserta semua FK constraint dan index
- Data dummy: minimal 10 baris per dimensi dan 30 baris fakta
- Minimal 5 query analitik berbeda yang mendemonstrasikan kekuatan star schema
- Satu query harus menggunakan minimal 3 dimensi sekaligus
- Satu query harus menggunakan agregasi (SUM, COUNT, AVG) dengan GROUP BY
- Satu query harus menunjukkan Year-over-Year atau perbandingan periode
Format: PDF (dokumen) + .sql (implementasi)
Deadline: H-1 sebelum Pertemuan 13
Pengumpulan: LMS dengan nama file: StarSchema_[KelompokX]_[Domain].pdf dan StarSchema_[KelompokX]_[Domain].sql
F. PERSIAPAN PERTEMUAN 13
F.1 Topik Pertemuan 13
Dimensional Modelling: Snowflake Schema & Slowly Changing Dimensions (SCD) â pertemuan ini memperdalam desain dimensional dengan dua topik lanjutan yang sangat praktis:
Topik 1: Snowflake Schema â variasi dari star schema di mana dimensi dinormalisasi. Kapan snowflake lebih baik dari star? Apa trade-off yang harus dipertimbangkan? Bagaimana mengubah star menjadi snowflake (dan sebaliknya)?
Topik 2: Slowly Changing Dimensions (SCD) â tantangan terbesar dalam dimensional modelling. Apa yang terjadi ketika data dimensi berubah? Pelanggan pindah kota â apakah riwayat penjualannya "ikut pindah"? Kolom SCD yang sudah kita sisipkan di Pertemuan 12 (berlaku_dari, berlaku_sampai, is_current) akan diaktivasi dan dijelaskan mekanismenya secara penuh. Tiga tipe SCD (Type 1, Type 2, Type 3) beserta trade-off masing-masing dibahas dengan contoh SQL.
F.2 Pertanyaan Pemantik untuk Pertemuan 13
Dari star schema yang sudah kamu rancang di Pertemuan 12, pikirkan:
-
Dalam
dim_produkkamu, jika seorang pemasok (supplier) berganti nama perusahaan, apakah kamu ingin riwayat penjualan lama "tetap menggunakan nama lama" atau "berubah mengikuti nama baru"? Ini adalah pertanyaan inti SCD! -
Dalam
dim_pelanggankamu, kamu sudah menyisipkan kolomberlaku_dari,berlaku_sampai, danis_current. Apa menurutmu fungsi dari ketiga kolom ini? Bagaimana cara menggunakannya dalam query? -
Jika
dim_produkmemiliki hierarki: Produk â Subkategori â Kategori â Kelompok, apakah kamu akan tetap menggunakan star schema (flatten) atau memisahkan ke tabel-tabel berbeda (snowflake)? Apa pertimbanganmu?
F.3 Bacaan untuk Pertemuan 13
- Kimball & Ross, Chapter 5: "Procurement" (contoh SCD Type 2 dalam konteks bisnis nyata)
- Kimball & Ross, Chapter 6: "Order Management" (handling perubahan dimensi)
- Kimball Group Design Tip: "Slowly Changing Dimensions" â https://www.kimballgroup.com (opens in a new tab)
G. REFERENSI
G.1 Referensi Utama
-
Kimball, R. & Ross, M. (2013). The Data Warehouse Toolkit: The Definitive Guide to Dimensional Modeling (3rd Edition). Wiley. ISBN: 978-1118530801.
- Chapter 1: Dimensional Modeling Primer (review dari P11)
- Chapter 2: Kimball Techniques â Four-Step Process (bacaan utama P12)
- Chapter 3: Retail Sales (contoh star schema lengkap untuk retail)
- Chapter 4: Inventory (contoh semi-additive measures)
-
Elmasri, R. & Navathe, S. B. (2015). Fundamentals of Database Systems (7th Edition). Pearson.
- Chapter 29: Introduction to Data Warehousing and Data Mining
-
Hoberman, S. (2009). Data Modeling Made Simple (2nd Edition). Technics Publications.
- Chapter 11: Dimensional Data Modeling (ringkasan yang lebih mudah dipahami)
G.2 Referensi Online
- Kimball Group. "The 10 Essential Rules of Dimensional Modeling" â https://www.kimballgroup.com/2009/05/the-10-essential-rules-of-dimensional-modeling/ (opens in a new tab)
- Kimball Group. "Dimension Table Design Techniques" â https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/ (opens in a new tab)
- dbt Labs. "Dimensional Modeling in the Modern Data Stack" â https://www.getdbt.com/analytics-engineering/modular-data-modeling-technique/ (opens in a new tab)
- Draw.io / Diagrams.net â https://draw.io (opens in a new tab) (tool online gratis untuk membuat diagram star schema visual)
G.3 Video Resources
- Kahan Data Solutions â "Star Schema vs Snowflake Schema â When to Use Each" (YouTube)
- Kimball Group â "The Dimensional Modeling Manifesto" (YouTube)
- Alex The Analyst â "Fact Tables vs Dimension Tables" (YouTube â sangat visual, cocok untuk pemula)
- Data with Baraa â "How to Design a Star Schema from Scratch" (YouTube â step-by-step praktis)
G.4 Tools untuk Praktikum
- Draw.io / Diagrams.net â https://draw.io (opens in a new tab): diagram ER/star schema online dengan visual interface
- draw.io â https://draw.io (opens in a new tab): diagram bebas, bisa ekspor ke berbagai format
- MySQL Workbench â Reverse engineer DDL untuk visual schema
- DuckDB â https://duckdb.org (opens in a new tab): jalankan query analitik langsung di CSV tanpa setup server
H. LAMPIRAN
Lampiran A: Cheat Sheet â Kimball's Four-Step Process
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â KIMBALL FOUR-STEP DIMENSIONAL DESIGN PROCESS â
â â
â LANGKAH 1: PILIH PROSES BISNIS â
â âââââââââââââââââââââââââââââââââââââââââââââ â
â ⥠Tentukan satu proses bisnis yang jelas â
â ⥠Proses = aktivitas yang menghasilkan data terukur â
â ⥠Hindari kata abstrak: "analisis", "monitoring" â
â ⥠Lebih baik: "penjualan", "peminjaman", "kunjungan" â
â â
â LANGKAH 2: DEKLARASIKAN GRAIN â
â âââââââââââââââââââââââââââââââââââââââââââââ â
â ⥠Tulis grain dalam SATU KALIMAT â
â ⥠Pastikan menyebut level paling atomik â
â ⥠Contoh valid: "Satu baris per item baris (line item) â
â dalam satu pesanan pelanggan pada satu tanggal" â
â ⥠Semua dimensi dan measures harus sesuai grain â
â â
â LANGKAH 3: IDENTIFIKASI DIMENSI â
â âââââââââââââââââââââââââââââââââââââââââââââ â
â ⥠Jawab: Siapa? Apa? Kapan? Di mana? Bagaimana? â
â ⥠dim_waktu SELALU ada â
â ⥠Setiap dimensi harus konsisten dengan grain â
â ⥠Gunakan surrogate key sebagai PK â
â ⥠Simpan natural key sebagai kolom terpisah â
â ⥠Denormalize â flatten semua hierarki! â
â ⥠Tambahkan atribut derivatif (kelompok usia, rentang â
â harga, dll.) â
â â
â LANGKAH 4: IDENTIFIKASI MEASURES â
â âââââââââââââââââââââââââââââââââââââââââââââ â
â ⥠Hanya ukuran numerik pada level grain yang ditetapkan â
â ⥠Klasifikasikan: additive / semi-additive / non-additive â
â ⥠Prioritaskan measures yang additive â
â ⥠Identifikasi degenerate dimensions â
â ⥠Verifikasi: setiap measure ada di SETIAP baris? â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââLampiran B: Checklist Desain Star Schema
SEBELUM FINALISASI DESAIN, PERIKSA SEMUA ITEM BERIKUT:
GRAIN:
⥠Grain dideklarasikan dalam satu kalimat yang jelas
⥠Grain adalah tingkat paling atomik yang masuk akal bisnis
⥠Semua dimensi yang dipilih konsisten dengan grain
⥠Semua measures ada pada tingkat grain yang sama
DIMENSI:
⥠Minimal satu dimensi waktu (dim_waktu) ada
⥠Setiap dimensi punya surrogate key (INT AUTO_INCREMENT) sebagai PK
⥠Natural key dari sumber disimpan sebagai kolom terpisah (bukan PK)
⥠Dimensi di-denormalize (tidak ada FK dari dimensi ke tabel lain)
⥠Setiap dimensi punya minimal 5â8 atribut deskriptif
⥠Atribut derivatif (kelompok usia, rentang harga, dll.) sudah ditambahkan
⥠Kolom SCD disiapkan (berlaku_dari, berlaku_sampai, is_current)
untuk dimensi yang nilainya bisa berubah
TABEL FAKTA:
⥠Berisi FK ke semua dimensi yang relevan
⥠Berisi degenerate dimensions yang diperlukan
⥠Measures sudah teridentifikasi dan diklasifikasikan (add/semi/non-add)
⥠Tidak ada data deskriptif (teks yang seharusnya ada di dimensi)
⥠PK adalah composite dari FK-FK yang ada
⥠Index tambahan pada FK yang sering digunakan untuk filter
IMPLEMENTASI SQL:
⥠DDL dimensi dibuat SEBELUM DDL fakta
⥠FK constraint ke dimensi didefinisikan dengan benar
⥠Data dummy cukup representatif (minimal 10 baris per dimensi)
⥠Data dummy di fakta mencakup berbagai kombinasi dimensi
⥠Query analitik berjalan tanpa error
REVIEW AKHIR:
⥠Diagram konsisten dengan DDL
⥠Naming convention konsisten (kunci_xxx untuk PK/FK, dst.)
⥠Komentar SQL menjelaskan tujuan setiap tabel dan kolom kritisLampiran C: Template DDL Generik untuk Star Schema Baru
-- ============================================================
-- TEMPLATE STAR SCHEMA GENERIK
-- Ganti [NAMA_DOMAIN] dengan nama domain kalian
-- Ganti [PROSES_BISNIS] dengan proses bisnis yang dimodelkan
-- ============================================================
-- 1. Buat database warehouse
CREATE DATABASE IF NOT EXISTS dw_[nama_domain]
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
USE dw_[nama_domain];
-- 2. Dimensi Waktu (copy dari template P12 â selalu sama)
-- [lihat DDL dim_waktu di bagian C.7.2]
-- 3. Dimensi Utama 1 â ganti sesuai domain
CREATE TABLE dim_[nama_entitas_1] (
kunci_[entitas_1] INT UNSIGNED NOT NULL AUTO_INCREMENT,
id_[entitas_1]_src INT UNSIGNED NOT NULL, -- natural key
-- atribut deskriptif minimal 6 kolom:
[atribut_1] VARCHAR(?) NOT NULL,
[atribut_2] VARCHAR(?) NOT NULL,
-- ... tambahkan atribut deskriptif yang relevan
-- kolom SCD (untuk dimensi yang bisa berubah):
berlaku_dari DATE NOT NULL,
berlaku_sampai DATE NOT NULL DEFAULT '9999-12-31',
is_current TINYINT(1) NOT NULL DEFAULT 1,
CONSTRAINT pk_dim_[entitas_1] PRIMARY KEY (kunci_[entitas_1]),
INDEX idx_nk_[entitas_1] (id_[entitas_1]_src)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 4. [Buat dimensi lain dengan pola yang sama]
-- 5. Tabel Fakta (buat TERAKHIR setelah semua dimensi ada)
-- Grain: [tuliskan grain di sini sebagai komentar!]
CREATE TABLE fakta_[proses_bisnis] (
-- FK ke semua dimensi:
kunci_waktu INT UNSIGNED NOT NULL,
kunci_[entitas_1] INT UNSIGNED NOT NULL,
kunci_[entitas_2] INT UNSIGNED NOT NULL,
-- degenerate dimensions (jika ada):
id_[dokumen] INT UNSIGNED NOT NULL,
-- measures:
[measure_1] DECIMAL(15,2) NOT NULL, -- additive
[measure_2] DECIMAL(15,2) NOT NULL, -- additive
[measure_3] DECIMAL(15,2) NULL, -- non-additive â AVG saja
-- PK composite:
CONSTRAINT pk_fakta_[proses_bisnis]
PRIMARY KEY (kunci_waktu, kunci_[entitas_1], kunci_[entitas_2], id_[dokumen]),
-- FK constraints:
CONSTRAINT fk_[proses]_waktu
FOREIGN KEY (kunci_waktu) REFERENCES dim_waktu (kunci_waktu),
CONSTRAINT fk_[proses]_[entitas_1]
FOREIGN KEY (kunci_[entitas_1]) REFERENCES dim_[entitas_1] (kunci_[entitas_1])
-- [tambahkan FK untuk setiap dimensi]
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Fakta [Proses Bisnis] â Grain: [DEKLARASIKAN GRAIN DI SINI]';Lampiran D: Lembar Kerja Praktikum D.2 â Desain Star Schema Kelompok
LEMBAR KERJA DESAIN STAR SCHEMA KELOMPOK
Kelompok : _____ | Domain : ___________________
Anggota : _______________________________________
Tanggal : ___________________
LANGKAH 1 â PROSES BISNIS:
Proses yang dimodelkan:
_______________________________________________
LANGKAH 2 â GRAIN:
Grain (satu kalimat):
"Satu baris mewakili ___________________________
_____________________________________________"
Mengapa grain ini tepat?
_______________________________________________
LANGKAH 3 â DIMENSI:
Dimensi 1: dim_____________
Surrogate Key: _______________________
Natural Key : _______________________
Atribut:
1. _____________ (tipe: _______) Deskripsi: _______
2. _____________ (tipe: _______) Deskripsi: _______
3. _____________ (tipe: _______) Deskripsi: _______
4. _____________ (tipe: _______) Deskripsi: _______
5. _____________ (tipe: _______) Deskripsi: _______
6. _____________ (tipe: _______) Deskripsi: _______
Dimensi 2: dim_____________
[isi dengan format yang sama]
Dimensi 3: dim_____________
[isi dengan format yang sama]
Dimensi 4: dim_____________
[isi dengan format yang sama]
dim_waktu: [selalu ada â gunakan template standar]
LANGKAH 4 â TABEL FAKTA:
Nama tabel: fakta_____________
Foreign Keys:
⥠kunci_waktu â dim_waktu
⥠kunci________ â dim_______
⥠kunci________ â dim_______
⥠kunci________ â dim_______
Degenerate Dimensions:
⥠id_______________ (tidak punya tabel dimensi sendiri karena: _______)
Measures:
âââââââââââââââââââŦâââââââââââââââŦâââââââââââââââââââââââââââââââ
â Nama Kolom â Tipe â Alasan â
âââââââââââââââââââŧâââââââââââââââŧâââââââââââââââââââââââââââââââ¤
â â ⥠Additive â â
â â ⥠Semi-add â â
â â ⥠Non-add â â
âââââââââââââââââââŧâââââââââââââââŧâââââââââââââââââââââââââââââââ¤
â â ⥠Additive â â
â â ⥠Semi-add â â
â â ⥠Non-add â â
âââââââââââââââââââŧâââââââââââââââŧâââââââââââââââââââââââââââââââ¤
â â ⥠Additive â â
â â ⥠Semi-add â â
â â ⥠Non-add â â
âââââââââââââââââââ´âââââââââââââââ´âââââââââââââââââââââââââââââââ
PERTANYAAN ANALITIK yang bisa dijawab schema ini:
1. _____________________________________________
2. _____________________________________________PENUTUP
Pertemuan 12 adalah pertemuan paling teknis dan paling padat dalam babak analitik semester ini. Di sini kita bergerak dari pemahaman konseptual (P11) ke keterampilan merancang yang sesungguhnya.
Key Messages Pertemuan 12:
-
Grain adalah fondasi segalanya â sebelum memilih dimensi atau measures, deklarasikan grain dengan tepat dalam satu kalimat. Grain yang salah tidak bisa diperbaiki tanpa redesign total.
-
"Wide, fat, denormalized" â itu dimensi yang baik â filosofi dimensi adalah kebalikan dari normalisasi OLTP. Tambahkan atribut sebanyak mungkin, flatten semua hierarki, dan jangan takut dengan redundansi yang disengaja.
-
Kenali tipe measures sebelum menulis query â menjumlahkan (SUM) nilai non-additive atau semi-additive menghasilkan angka yang salah, bukan error SQL. Kesalahan ini sering tidak terdeteksi dan menyebabkan keputusan bisnis yang salah.
-
Surrogate key wajib, natural key tetap disimpan â keduanya punya peran yang berbeda dan keduanya diperlukan.
-
dim_waktu adalah investasi sekali pakai yang menguntungkan seumur panjang â populate sekali, gunakan untuk semua analisis temporal. Setiap kolom di dim_waktu adalah "free feature" untuk analitik yang tidak perlu dihitung berulang.
-
Star schema adalah penyederhanaan yang disengaja â satu hop JOIN dari fakta ke dimensi, query yang sederhana dan bersih, dan BI tools yang bahagia. Ini adalah tujuannya.
Koneksi ke Proyek Semester: Tugas P12 adalah Tahap 7 (terakhir!) dari proyek bertahap: Dimensional Model. Setelah ini diserahkan, kelompok sudah memiliki seluruh lapisan desain (Konseptual â Logis â Fisik â Dimensional) yang akan dipresentasikan di Pertemuan 15. Pertemuan 13 akan memperdalam desain ini dengan SCD dan snowflake schema.
Disusun oleh: Mohammad Reza Maulana, M.Kom Program Studi Sains Data Fakultas Ekonomi dan Bisnis Islam UIN K.H. Abdurrahman Wahid Pekalongan
Revisi: Februari 2026