Gudang data yang tidak terdokumentasi hanya berguna bagi pembangunnya; setiap analis baru harus menebak arti kolom dan aturan metrik dari potongan SQL yang tersebar. Pada bagian penutup ini kita menuliskan dokumentasi model TokoKita: kamus data yang diverifikasi langsung dari gudang aktif, diagram lineage yang menelusuri perjalanan setiap tabel, dan definisi metrik sebagai kontrak. Pendekatannya mengikuti chapter Dokumentasi Model Data dan Data Lineage: dokumentasi harus ikut hidup bersama kode, bukan menjadi dokumen terpisah yang cepat usang.
Kamus Data #
Dokumentasi kolom paling mudah usang, jadi kita ambil daftar kolom langsung dari gudang yang sedang berjalan:
con = db.connect()
print("=== kolom fact_pesanan (PRAGMA table_info) ===")
for baris in con.execute("PRAGMA table_info('fact_pesanan')").fetchall():
print(f" {baris[1]:14s} {baris[2]}")
print()
print("=== jumlah kolom per tabel gudang (duckdb_columns) ===")
for baris in con.execute("""
SELECT table_name, COUNT(*) AS jumlah_kolom
FROM duckdb_columns()
WHERE table_name LIKE 'dim_%' OR table_name = 'fact_pesanan'
GROUP BY table_name
ORDER BY table_name
""").fetchall():
print(f" {baris[0]:14s} {baris[1]} kolom")Output yang Dihasilkan:
=== kolom fact_pesanan (PRAGMA table_info) ===
pesanan_id VARCHAR
baris INTEGER
tanggal_sk INTEGER
pelanggan_sk INTEGER
produk_sk INTEGER
toko_sk INTEGER
jumlah INTEGER
harga_satuan BIGINT
diskon BIGINT
total BIGINT
status VARCHAR
=== jumlah kolom per tabel gudang (duckdb_columns) ===
dim_pelanggan 11 kolom
dim_produk 8 kolom
dim_tanggal 10 kolom
dim_toko 8 kolom
fact_pesanan 11 kolomKeluaran tersebut adalah kerangka kamus data; deskripsi tiap kolom kita lengkapi menjadi tabel berikut:
| Tabel | Kolom penting | Keterangan |
|---|---|---|
fact_pesanan | pesanan_id, baris | degenerate dimension, pembeda grain satu baris pesanan |
tanggal_sk, pelanggan_sk, produk_sk, toko_sk | foreign key ke dimensi | |
jumlah, harga_satuan, diskon | measure; harga_satuan non-additive | |
total | measure additive: jumlah * harga_satuan - diskon | |
status | selesai, dibatalkan, dikembalikan | |
dim_pelanggan | nk_hash, attr_hash | pelacak natural key dan pendeteksi perubahan |
valid_from, valid_to, is_current | masa berlaku versi SCD Type 2 | |
dim_produk, dim_toko | *_sk, *_id | surrogate key dan natural key |
dim_tanggal | tanggal_sk | smart key YYYYMMDD |
Kamus lengkap per kolom sebaiknya tinggal berdampingan dengan model, seperti deskripsi pada schema.yml dbt yang dibahas chapter Dokumentasi Model Data; dokumentasi resminya di https://docs.getdbt.com/docs/build/documentation
.
Lineage Model #
Lineage menjawab pertanyaan “dari mana tabel ini berasal dan siapa memakainya”. Seluruh alur proyek kita padatkan dalam satu diagram:
Membaca dari kiri: lima CSV sumber menjadi lima tabel staging, empat model dimensi dibangun dari staging, lalu fact_pesanan menggabungkan staging pesanan dengan keempat dimensi. Perhatikan dua tepi khusus: stg_pelanggan_update mengalir ke dim_pelanggan melalui SCD Type 2 Bagian 6, dan dim_tanggal berdiri sendiri karena kalender dibangkitkan, bukan dibaca dari sumber. Dua kotak paling kanan adalah contoh konsumen: laporan GMV dan tingkat pembatalan dari Bagian 1.
Definisi Metrik sebagai Kontrak #
Dokumentasi tertutup dengan menghubungkan kamus data ke models/metric_definitions.yaml dari Bagian 1. Enam metrik pada berkas tersebut kita hitung ulang dari gudang aktif:
print("=== ringkasan isi gudang (metrik dari metric_definitions) ===")
gmv, pesanan, item = con.execute("""
SELECT SUM(total) FILTER (WHERE status = 'selesai'),
COUNT(DISTINCT pesanan_id) FILTER (WHERE status = 'selesai'),
SUM(jumlah) FILTER (WHERE status = 'selesai')
FROM fact_pesanan
""").fetchone()
print(f" gmv : Rp{gmv:,}".replace(",", "."))
print(f" jumlah_pesanan : {pesanan}")
print(f" jumlah_item_terjual : {item}")
print(f" nilai_pesanan_rata_rata: Rp{gmv / pesanan:,.0f}".replace(",", "."))Output yang Dihasilkan:
=== ringkasan isi gudang (metrik dari metric_definitions) ===
gmv : Rp2.890.000
jumlah_pesanan : 17
jumlah_item_terjual : 51
nilai_pesanan_rata_rata: Rp170.000GMV sebesar Rp2.890.000 dari 17 pesanan selesai adalah angka yang sama yang akan dihitung analis mana pun, karena filter status melekat pada definisi, bukan pada kebiasaan masing-masing. Inilah makna kontrak: metric_definitions.yaml, fact table, dan laporan saling mengunci sehingga perbedaan angka antar tim menjadi gejala galat data yang perlu ditelusuri, bukan perbedaan pendapat.
Menutup Proyek #
Sembilan bagian telah kita lalui: kebutuhan analitik diturunkan menjadi grain dan metrik, star schema dirancang lalu dibangun dengan surrogate key dan pelacakan hash, pipeline deklaratif menjalankan model SQL gaya dbt melalui DuckDB, perubahan dimensi dicatat sebagai SCD Type 2, kualitas data dijaga lima pemeriksaan plus 36 uji pytest, dan manfaat desain diukur jujur dengan EXPLAIN ANALYZE. Perintah python3 -m src.pipeline membangun ulang seluruh gudang dari CSV kapan pun diperlukan; itulah janji idempotensi yang kita pegang sejak Bagian 3.
Gudang data ini masih berjalan sebagai satu perintah manual. Pada praktik nyata, pemuatan harian perlu dijadwalkan, diberi retry, dan dipantau eksekusinya; itulah pekerjaan orkestrasi workflow. Perjalanan berlanjut ke proyek berikutnya: Proyek: Orkestrasi Pipeline dengan Airflow.