Hari 1 — Data Quality dalam Pipeline: 5 Dimensi Kualitas Data
Senin, 2 jam. Konsep murni — pakai tabel fact_sales/dim_customer/dim_product/dim_date hasil pipeline Minggu 3 sebagai contoh kasus.
Materi ini fondasi literal untuk Data Governance Minggu 5 (lihat
minggu_5.md) — istilah “dimensi kualitas data” akan terus dipakai sampai akhir roadmap, bukan cuma jargon 1 minggu.
Tujuan Belajar
- Menyebutkan dan menjelaskan 5 dimensi kualitas data: completeness, uniqueness, validity, consistency, timeliness
- Untuk data di
fact_sales/dimension table Minggu 3, merumuskan aturan konkret per dimensi - Menjelaskan kenapa “pipeline tidak error” tidak sama dengan “data valid”
- Menjelaskan konsep fail-fast dalam konteks data quality gate
Untuk Instruktur: Mindset Shift
Analogi paling langsung buat developer: dimensi data quality itu setara assertion/test case, tapi untuk data, bukan untuk kode. Developer sudah terbiasa menulis assert response.status == 200 atau unit test yang mengecek “fungsi ini menghasilkan output yang benar”. Data quality check melakukan hal yang sama persis, tapi objeknya baris-baris data: “apakah baris ini masuk akal?”
Poin yang wajib ditekankan di awal sesi: Airflow (Minggu 3) tahu apakah kode-nya error, tapi tidak tahu apakah datanya benar. Task load_to_warehouse di DAG Minggu 3 akan tetap sukses (hijau) walau isinya Quantity = -99999 atau Customer ID kosong semua — karena secara teknis, pd.read_parquet() dan .to_sql() tidak error menjalankan itu. Data quality check adalah lapisan tambahan yang secara eksplisit memeriksa isi datanya, bukan cuma “apakah kodenya jalan tanpa exception”.
Konsep & Sintaks
5 Dimensi Kualitas Data
| Dimensi | Pertanyaan yang Dijawab | Contoh Aturan untuk fact_sales/dimension Minggu 3 |
|---|---|---|
| Completeness | Apakah data yang seharusnya ada, benar-benar ada (tidak NULL/kosong)? | customer_id, invoice, stock_code di fact_sales tidak boleh NULL |
| Uniqueness | Apakah tidak ada duplikasi yang tidak seharusnya ada? | Kombinasi invoice + stock_code tidak boleh duplikat (1 produk cuma muncul 1x per invoice) |
| Validity | Apakah nilai data sesuai format/range/tipe yang diharapkan? | unit_price dan quantity harus > 0; country di dim_customer harus ada di daftar negara valid |
| Consistency | Apakah data konsisten secara logis antar kolom/tabel? | revenue harus sama dengan quantity × unit_price; customer_id di fact_sales harus ada padanannya di dim_customer |
| Timeliness | Apakah data cukup “segar” sesuai kebutuhan (tidak basi)? | dim_date/fact_sales hasil run hari ini harus berisi data sampai kemarin, bukan data 3 bulan lalu (pipeline gagal jalan diam-diam) |
Cara mudah mengingat: 4 dimensi pertama (completeness, uniqueness, validity, consistency) menjawab “apakah isi datanya benar?”, dimensi terakhir (timeliness) menjawab “apakah datanya masih relevan waktunya?” — dimensi ini sering terlewat karena tidak terlihat dari isi satu baris data, tapi dari kapan data itu terakhir diperbarui dibanding kapan seharusnya.
Kenapa Bukan Cuma “Data Bersih vs Kotor”
Developer sering menyederhanakan data quality jadi 1 pertanyaan besar (“apakah datanya bersih?”), padahal itu 5 pertanyaan independen — data bisa lolos 1 dimensi tapi gagal di dimensi lain:
- Baris dengan
customer_idterisi (lolos completeness) tapicustomer_id-nya tidak ada didim_customer(gagal consistency). - Baris dengan
unit_price = 15.00(lolos validity, angka positif wajar) tapirevenuetersimpan999999.00padahalquantity × unit_priceharusnya jauh lebih kecil (gagal consistency). - Tidak ada baris duplikat sama sekali (lolos uniqueness) tapi data terakhir yang masuk 2 bulan lalu (gagal timeliness, karena pipeline diam-diam berhenti jalan tanpa ada yang sadar).
Memisahkan jadi 5 dimensi memaksa pemeriksaan yang spesifik dan terukur, bukan perasaan umum “kelihatannya oke”.
Fail-Fast: Kenapa Urutan Pemeriksaan Penting
Fail-fast = begitu ditemukan pelanggaran, pipeline berhenti segera di titik itu — tidak melanjutkan ke tahap berikutnya dengan data yang sudah diketahui bermasalah. Ini prinsip yang sama dengan validasi input di awal fungsi (guard clause) di software development — developer sudah terbiasa: cek validitas argumen di awal fungsi, bukan di tengah-tengah setelah sebagian efek samping sudah terjadi.
Untuk pipeline data, ini berarti data quality check wajib ditaruh sebelum data menyentuh sistem yang dipakai orang lain (warehouse, dashboard). Kalau check ditaruh setelah load (seperti pola sederhana di materi/minggu_3/latihan_pipeline_mini_project.md), data yang salah sudah telanjur ada di warehouse saat masalahnya baru ketahuan — analyst atau dashboard yang kebetulan mengakses warehouse di jendela waktu itu bisa saja sudah melihat/memakai data yang salah. Ini alasan DAG Minggu 4 (latihan_dq_streaming_mini_project.md) mengubah urutan jadi extract → transform → data_quality_check → load → notify — check dipindah sebelum load, persis prinsip fail-fast.
Contoh Kasus
Bayangkan fact_sales hari ini menerima baris-baris berikut dari pipeline Minggu 3. Untuk tiap baris, dimensi apa yang dilanggar?
| Baris | invoice | stock_code | customer_id | quantity | unit_price | revenue |
|---|---|---|---|---|---|---|
| A | 536365 | 85123A | NULL | 6 | 2.55 | 15.30 |
| B | 536366 | 71053 | 17850 | 6 | 3.39 | 20.34 |
| B (lagi) | 536366 | 71053 | 17850 | 6 | 3.39 | 20.34 |
| C | 536367 | 84406B | 17850 | 8 | -2.75 | -22.00 |
| D | 536368 | 22752 | 17850 | 2 | 7.65 | 999.00 |
- Baris A:
customer_idkosong → pelanggaran completeness. - Baris B (duplikat): kombinasi
invoice+stock_code(536366, 71053) muncul 2x → pelanggaran uniqueness. - Baris C:
unit_pricenegatif → pelanggaran validity (harga tidak masuk akal secara bisnis, beda dariquantitynegatif yang sudah dikategorikan sebagai retur di Minggu 2–3). - Baris D:
revenue(999.00) tidak sama denganquantity × unit_price(2 × 7.65 = 15.30) → pelanggaran consistency.
Latihan serupa dengan skenario timeliness ada di bagian Latihan.
Kesalahan Umum
- Menganggap “tidak ada error saat pipeline jalan” berarti “data valid”. Ini miskonsepsi inti minggu ini — sudah dibahas di atas, tapi wajar diulang karena sangat mudah terlewat oleh developer yang terbiasa berpikir dalam kerangka “ada exception vs tidak ada exception”.
- Mencampur 5 dimensi jadi satu pemeriksaan besar yang samar (“cek apakah data OK”) alih-alih aturan spesifik per dimensi. Aturan yang samar susah diotomasi dan susah didiagnosis kalau gagal — bandingkan
assert data_ok(df)(tidak jelas apa yang salah kalau gagal) vs 5 assertion terpisah yang jelas dimensi mana yang gagal. - Fokus cuma ke completeness/validity, lupa consistency. Completeness (null check) dan validity (range check) paling gampang ditulis, jadi sering jadi satu-satunya yang diperiksa — padahal bug data yang paling berbahaya justru sering muncul di consistency (angka yang masing-masing “terlihat wajar” sendiri-sendiri, tapi tidak nyambung logikanya satu sama lain, seperti Baris D di atas).
- Meletakkan data quality check setelah data sudah dipakai sistem lain (bukan fail-fast). Deteksi telat tetap lebih baik dari tidak ada deteksi sama sekali, tapi konsekuensinya beda jauh dari mencegah data buruk masuk sejak awal.
Latihan
- Untuk skenario “pipeline
ecommerce_etl_pipelineseharusnya jalan tiap hari jam 2 pagi, tapi karena container Airflow down 3 hari, tidak ada run baru sejak 3 hari lalu — namun kalau dicek, semua data yang ada difact_salessebenarnya valid (tidak ada null, tidak ada duplikat, angka semua masuk akal)” — dimensi apa yang dilanggar? Kenapa 4 dimensi lain tidak cukup untuk menangkap masalah ini? - Rumuskan aturan completeness dan validity untuk
dim_date(kolom:date_id,full_date,day,month,quarter,year,is_weekend— lihatmateri/minggu_3/hari_2_data_modeling.md). - Seorang rekan bilang “consistency check itu berlebihan, kalau completeness dan validity sudah lolos, datanya pasti sudah benar.” Bantah pernyataan ini dengan contoh konkret dari
fact_sales. - Rancang aturan uniqueness untuk
dim_customerdandim_product(bukanfact_sales) — apa yang seharusnya tidak boleh duplikat di masing-masing tabel ini, dan kenapa itu penting untukJOINyang benar kefact_sales?
Kunci Jawaban & Pembahasan
1. Ini pelanggaran timeliness — datanya sendiri (yang sudah ada) valid di 4 dimensi lain, tapi data yang seharusnya sudah ada (3 hari terbaru) tidak pernah masuk. Completeness cuma memeriksa apakah kolom di baris yang ada terisi, bukan apakah baris/periode waktu yang seharusnya ada memang ada — ini beda level pemeriksaan. Uniqueness, validity, consistency juga sama-sama cuma memeriksa baris yang sudah ada, tidak bisa mendeteksi baris yang hilang seluruhnya. Ini kenapa timeliness butuh jenis pemeriksaan berbeda: biasanya “apakah ada data baru sejak timestamp X” atau “apakah MAX(invoice_date) cukup dekat dengan hari ini” — bukan pemeriksaan per-baris seperti 4 dimensi lainnya.
2.
Completeness: date_id, full_date, day, month, quarter, year, is_weekend semuanya tidak boleh NULL
(dim_date biasanya di-generate penuh, jadi seharusnya tidak ada NULL sama sekali —
kalau ada, kemungkinan bug di logic generate-nya sendiri)
Validity: month antara 1-12
quarter antara 1-4
day antara 1-31 (dan idealnya konsisten dengan month, misal bukan 30 Februari)
is_weekend harus boolean (True/False), bukan tipe lain
full_date harus tipe date/timestamp valid, bukan string sembarang
3. Contoh: baris dengan quantity = 100, unit_price = 50.00 — keduanya lolos validity (sama-sama angka positif, masuk akal secara individual). Tapi kalau revenue yang tersimpan di baris itu ternyata 5.00 (bukan 100 × 50 = 5000), itu jelas ada yang salah — mungkin bug di formula perhitungan revenue saat transform, atau kolom yang salah ke-mapping. Completeness dan validity, sekeras apapun diperiksa, tidak akan pernah menangkap masalah ini karena masing-masing kolom (quantity, unit_price, revenue) secara individual tetap terlihat “valid” — masalahnya ada di hubungan logis antar kolom, dan cuma consistency check yang secara eksplisit memeriksa hubungan itu.
4. dim_customer: customer_id harus unik (1 baris per customer — kalau ada 2 baris customer_id = 17850 dengan country berbeda, JOIN dari fact_sales ke dim_customer bisa menghasilkan baris ganda/ambigu, bikin agregasi revenue jadi salah karena baris fact ter-duplikasi lewat join). dim_product: stock_code harus unik (alasan sama persis — 1 produk harusnya 1 baris deskripsi). Ini kenapa uniqueness dimension table sama pentingnya dengan uniqueness fact table: pelanggaran di dimension table menular ke hasil query manapun yang melakukan JOIN ke tabel itu, walau fact table-nya sendiri sudah bersih.