Topik ini membahas dua teknik desain dimensi yang paling sering dipakai pada pemodelan Kimball, yaitu degenerate dimension untuk atribut transaksi dan slowly changing dimension untuk atribut yang berubah seiring waktu. Keduanya dijelaskan mulai dari masalah yang diselesaikannya. Pembahasan ditutup dengan demonstrasi slowly changing dimension tipe 2 yang dijalankan di DuckDB, sehingga mekanisme penutupan baris lama dan pembukaan baris baru terlihat pada keluaran aslinya.
Degenerate dimension: atribut transaksi tanpa tabel dimensi#
Degenerate dimension adalah atribut kejadian seperti nomor transaksi yang disimpan pada tabel fakta tanpa membentuk tabel dimensi, karena tidak ada atribut lain yang menyertainya. Nomor peminjaman pada perpustakaan dan nomor struk pada kasir toko alat tulis adalah contohnya. Nomor itu memang berperan seperti dimensi karena dapat dipakai memfilter dan mengelompokkan, tetapi isinya hanya satu kolom sehingga tabel dimensi terpisah justru membebani skema tanpa menambah informasi.
Degenerate dimension berguna untuk dua keperluan praktis. Pertama, penelusuran balik, yaitu menemukan kembali kejadian asli di sistem sumber dari nomornya. Kedua, penghitungan kejadian unik, misalnya berapa jumlah transaksi yang dilakukan seorang kasir, yang dijawab dengan penghitungan nilai unik kolom tersebut. Definisi Kimball menempatkannya sebagai kunci dimensi tanpa atribut yang menetap di fakta, sebagaimana tampak pada potongan skema berikut.
-- tidak-dijalankan
CREATE TABLE fakta_penjualan_kasir (
no_transaksi VARCHAR NOT NULL, -- degenerate dimension
kunci_produk INTEGER NOT NULL,
kunci_waktu INTEGER NOT NULL,
jumlah INTEGER NOT NULL,
total_harga INTEGER NOT NULL
)Potongan di atas menunjukkan bahwa no_transaksi diperlakukan seperti kunci dimensi, tetapi menetap di fakta dan tidak memiliki tabel pemiliknya. Pada fakta dengan grain satu baris per item struk, nomor yang sama berulang di beberapa baris, sehingga penghitungan transaksi menggunakan nilai uniknya dan bukan jumlah barisnya.
Slowly changing dimension: atribut dimensi yang berubah#
Slowly changing dimension (SCD) adalah teknik menangani atribut dimensi yang nilainya berubah seiring waktu, misalnya kota tempat tinggal pelanggan atau lokasi rak di perpustakaan. Persoalannya muncul karena tabel fakta terhubung ke dimensi lewat kunci. Apabila atribut dimensi ditimpa, seluruh angka historis tiba-tiba dibaca dengan konteks yang baru, dan analisis atas masa lalu menjadi menyesatkan.
Metode Kimball menetapkan beberapa tipe penanganan, dan tiga di antaranya dipakai paling sering. Tabel berikut membandingkan ketiganya.
| Tipe | Penanganan | Riwayat | Penerapan yang cocok |
|---|---|---|---|
| Tipe 1 | nilai lama ditimpa | hilang | perbaikan salah ketik yang tidak perlu dianalisis |
| Tipe 2 | baris baru dibuka, baris lama ditutup | utuh per periode | perubahan yang perlu dianalisis, misalnya pindah kota |
| Tipe 3 | kolom tersendiri untuk nilai sebelumnya | satu langkah | perubahan besar yang cukup diketahui nilai sebelumnya |
Tipe 2 adalah pilihan paling lazim di warehouse karena mempertahankan riwayat tanpa memengaruhi kueri lain. Setiap perubahan menutup baris lama dengan mengisi batas akhir berlakunya, lalu membuka baris baru dengan kunci surogat yang berbeda. Pasangan kolom rentang berlaku, ditambah penanda baris aktif, menjaga setiap fakta tetap terhubung ke versi dimensi yang benar pada waktunya.
Demonstrasi SCD tipe 2#
Skrip berikut memuat versi awal dim_pelanggan berisi tiga pelanggan, lalu menghadapi kejadian perpindahan kota pada satu pelanggan. Baris lamanya ditutup, baris baru dibuka, dan isi tabel dicetak utuh. Di akhir, dua kueri versi menunjukkan atribut mana yang berlaku pada tanggal tertentu.
"""Memperagakan slowly changing dimension tipe 2 pada dimensi pelanggan."""
import duckdb
con = duckdb.connect(":memory:")
con.execute("""
CREATE TABLE dim_pelanggan (
kunci_pelanggan INTEGER PRIMARY KEY,
id_pelanggan INTEGER NOT NULL,
nama VARCHAR NOT NULL,
kota VARCHAR NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE NOT NULL,
status VARCHAR NOT NULL
)
""")
# Muat versi awal tiga pelanggan
con.executemany("INSERT INTO dim_pelanggan VALUES (?, ?, ?, ?, ?, ?, ?)", [
(101, 1, "Ali", "Bandung", "2026-01-01", "9999-12-31", "aktif"),
(102, 2, "Budi", "Bandung", "2026-01-01", "9999-12-31", "aktif"),
(103, 3, "Citra", "Semarang", "2026-01-01", "9999-12-31", "aktif"),
])
# Kejadian pada 2026-03-01: Citra pindah kota
# SCD tipe 2: tutup baris lama, lalu buka baris baru dengan kunci surogat sendiri
con.execute("""
UPDATE dim_pelanggan
SET valid_to = DATE '2026-02-28', status = 'riwayat'
WHERE id_pelanggan = 3 AND status = 'aktif'
""")
con.execute("""
INSERT INTO dim_pelanggan
VALUES (104, 3, 'Citra', 'Yogyakarta', DATE '2026-03-01', DATE '9999-12-31', 'aktif')
""")
print("Isi dim_pelanggan setelah pembaruan SCD tipe 2:")
print(" kunci id nama kota dari sampai status")
rows = con.execute("SELECT * FROM dim_pelanggan ORDER BY kunci_pelanggan").fetchall()
for kunci, id_p, nama, kota, dari, sampai, status in rows:
print(f" {kunci:<6} {id_p:<3} {nama:<6} {kota:<13} {dari} {sampai} {status}")
# Kueri versi: atribut pelanggan yang berlaku pada sebuah tanggal
for tanggal in ("2026-02-15", "2026-03-05"):
kota = con.execute("""
SELECT kota FROM dim_pelanggan
WHERE id_pelanggan = 3
AND CAST(? AS DATE) BETWEEN valid_from AND valid_to
""", [tanggal]).fetchone()[0]
print(f"Kota Citra pada {tanggal}: {kota}")Isi dim_pelanggan setelah pembaruan SCD tipe 2:
kunci id nama kota dari sampai status
101 1 Ali Bandung 2026-01-01 9999-12-31 aktif
102 2 Budi Bandung 2026-01-01 9999-12-31 aktif
103 3 Citra Semarang 2026-01-01 2026-02-28 riwayat
104 3 Citra Yogyakarta 2026-03-01 9999-12-31 aktif
Kota Citra pada 2026-02-15: Semarang
Kota Citra pada 2026-03-05: YogyakartaKeluarannya memperlihatkan empat baris untuk tiga pelanggan, dan selisih itulah inti tipe 2. Baris Citra versi Semarang berstatus riwayat dengan rentang berlaku yang tertutup, sedangkan versi Yogyakarta berstatus aktif dengan kunci surogat baru bernilai 104. Kueri versi lalu menjawab dengan tepat bahwa Citra berada di Semarang pada pertengahan Februari dan di Yogyakarta pada awal Maret. Baris fakta yang terjadi sebelum perpindahan tetap menunjuk kunci lama, sehingga angka historis tidak pernah berubah di belakang analisis.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul saat teknik dimensi ini dipraktikkan.
- Memakai tipe 1 tanpa menimbang kebutuhan analisis historis. Penyebabnya, penimpaan nilai terasa sederhana, padahal angka masa lalu ikut dibaca dengan konteks baru dan laporan yang sudah terbit tidak dapat direkonsiliasi. Perbaikannya, gunakan tipe 2 untuk atribut yang dianalisis sepanjang waktu dan sisakan tipe 1 untuk perbaikan kesalahan ketik.
- Menyisipkan baris baru tanpa menutup baris lama. Penyebabnya, dua versi aktif hidup bersamaan sehingga join dari fakta menggandakan baris dan total membengkak. Perbaikannya, tutup baris lama dan buka baris baru dalam satu transaksi, lalu uji dengan kueri yang menghitung baris aktif per kunci alami (natural key), yaitu kunci asli dari sistem sumber.
- Menjadikan kunci alami sebagai kunci join dari fakta. Penyebabnya, versi lama dan versi baru berbagi kunci yang sama sehingga riwayat tidak dapat dibedakan. Perbaikannya, hubungkan fakta ke kunci surogat yang berbeda untuk setiap versi, dan simpan kunci alami hanya sebagai atribut referensi.
Ringkasan#
- Degenerate dimension menyimpan atribut transaksi seperti nomor struk langsung pada fakta karena atribut itu tidak memiliki kolom pembanding yang layak dimasukkan ke tabel dimensi.
- Slowly changing dimension menangani atribut dimensi yang berubah, dengan tipe 1 menimpa, tipe 2 membuka baris baru, dan tipe 3 menyimpan satu nilai lampau.
- SCD tipe 2 menutup baris lama, membuka baris baru dengan kunci surogat berbeda, dan menjaga setiap fakta terhubung ke versi yang benar pada waktunya.
- Kesalahan paling merugikan adalah kehilangan riwayat secara tak disengaja dan baris aktif ganda, keduanya membuat angka analitik menyesatkan.
Referensi#
- Dimensional Modeling Techniques — Kimball Group — Daftar teknik resmi Kimball yang mencakup degenerate dimension dan slowly changing dimensions beserta tipe-tipenya.