Pada Proyek: Streaming Data dengan Kafka kita memproses event begitu data tiba; pada proyek ini kita menghadapi sisi lainnya: data yang sudah beristirahat sebagai berkas historis dan harus diolah secara batch. Dataset yang kita proses adalah hasil ekspor basis data transaksional TokoKita: 800 ribu pesanan, 1,6 juta baris pesanan, 60 ribu pelanggan, dan 400 produk — sekitar 22,6 MB berformat parquet. Mesin pengolahnya adalah Apache Spark 4.2.0 mode lokal dengan PySpark sebagai antarmuka Python, persis seperti yang kita pelajari pada chapter Apache Spark; dokumentasi resmi ada di https://spark.apache.org/docs/latest/
dan setiap fitur yang dipakai proyek ini tercantum di sana. Seluruh angka pada sembilan bagian proyek ini adalah hasil eksekusi nyata pada mesin uji dua CPU dengan master("local[1]"); tidak ada satu pun blok keluaran yang dikarang.
Hasil akhir proyek ini berupa:
- dataset TokoKita deterministik: empat tabel parquet yang dibangkitkan dari rumus modular sehingga dapat direplikasi di Python murni,
- satu SparkSession
local[1]yang dikonfigurasi dari satu berkas YAML (UI dimatikan, logERROR, shuffle 8 partition, AQE aktif), - pipeline end-to-end: baca parquet, transformasi, join, agregasi, lalu simpan partition by bulan disertai verifikasi baca ulang,
- pengukuran nyata: broadcast vs sort-merge join, UDF vs built-in, cache dingin vs panas, column pruning, dan predicate pushdown,
- pembacaan query plan mode
formatted,simple, danextended, termasuk penandaPartitionFiltersdanPushedFilters, dan - 31 uji pytest yang lulus penuh dalam satu suite serial.
Prasyarat #
Sebelum mulai, pastikan kita telah memahami chapter berikut karena seluruh keputusan teknis pada proyek ini merujuk ke sana:
- Apache Spark dan Spark DataFrames — arsitektur eksekusi serta API DataFrame yang dipakai seluruh modul,
- Spark SQL — dasar optimizer Catalyst yang rencananya kita baca pada Bagian 7,
- Spark Joins serta Shuffle dan Skew — mekanisme broadcast join dan biaya shuffle yang diukur pada Bagian 5,
- Spark Partitioning — perbedaan partition penyimpanan dan partition task yang diatur pada Bagian 6,
- Spark Performance dan Kapan Menggunakan Spark — kerangka kerja optimasi serta batas kapan Spark tepat dipakai.
Seluruh kode berjalan pada Python 3.12 dengan PySpark 4.2.0 di atas OpenJDK 21; dependensi lain hanya PyYAML dan pytest.
Struktur Proyek #
pemrosesan-data-dengan-spark/
├── _index.md
├── part-1-memahami-dataset-besar/
├── part-2-menyiapkan-spark/
├── part-3-membaca-data-terdistribusi/
├── part-4-melakukan-transformasi/
├── part-5-melakukan-join-dan-aggregasi/
├── part-6-mengatur-partition/
├── part-7-menganalisis-query-plan/
├── part-8-mengoptimalkan-job/
├── part-9-menyimpan-hasil/
├── config/ (spark-local.yaml + requirements.txt)
├── data/ (parquet 22,6 MB; data/hasil/ ditulis pipeline)
├── src/ (session, generate_data, transformasi, joins, partisi, plan, optimasi, simpan, pipeline)
└── tests/ (31 uji pytest untuk seluruh modul)Seluruh berkas kode pada folder config/, data/, src/, dan tests/ tersedia pada bagian Berkas Sumber di bawah halaman ini. Setiap bagian pengerjaan merujuk ke berkas yang sama sehingga kondisi proyek tetap utuh di setiap tahap.
Tahapan Pengerjaan #
Proyek dikerjakan dalam sembilan bagian berurutan. Setiap bagian menghasilkan artefak yang dapat dijalankan dan diuji:
- Bagian 1 memahami dataset: skema, distribusi, dan struktur fisik parquet.
- Bagian 2 menyiapkan Spark: satu berkas konfigurasi, satu SparkSession.
- Bagian 3 membaca data terdistribusi: schema inference vs eksplisit, partition pruning.
- Bagian 4 melakukan transformasi: kolom turunan,
whenbertingkat, null, dan UDF. - Bagian 5 melakukan join dan agregasi: broadcast vs sort-merge, metrik bulanan.
- Bagian 6 mengatur partition:
repartition,coalesce, dan berkas kecil. - Bagian 7 menganalisis query plan:
formatted,simple, danextended. - Bagian 8 mengoptimalkan job: cache, column pruning, predicate pushdown.
- Bagian 9 menyimpan hasil: parquet partition by bulan, verifikasi baca ulang.
Mulailah dari Bagian 1 dan ikuti urutannya karena setiap bagian dibangun di atas keputusan bagian sebelumnya.
Kontrak Pengujian #
Dua perintah berikut menjadi bukti bahwa proyek sehat pada setiap tahap. Perintah pertama menjalankan pipeline end-to-end; perintah kedua menjalankan seluruh uji:
cd content/data-engineering/proyek/pemrosesan-data-dengan-spark
python3 -m src.pipeline
python3 -m pytest tests/ -qKedua perintah tersebut dijalankan nyata pada Bagian 9; keluarannya ditampilkan apa adanya, bukan karangan. Seluruh durasi pada proyek ini diukur pada mesin uji dua CPU (sekitar 3,9 GB RAM) dengan satu inti CPU per sesi — angka Anda akan berbeda antar mesin, namun pola dan rasionya stabil.
Bedah skema, distribusi, dan tata letak parquet dataset TokoKita sebelum satu transformasi pun dijalankan.
Buka → # Bagian 2: Menyiapkan SparkBangun satu SparkSession local[1] yang seluruh konfigurasinya dibaca dari satu berkas YAML.
Buka → # Bagian 3: Membaca Data TerdistribusiBaca parquet terdistribusi dengan schema inference, schema eksplisit, dan bukti partition pruning pada query plan.
Buka → # Bagian 4: Melakukan TransformasiTerapkan withColumn, when bertingkat, penanganan null, dan ukur biaya UDF Python dibanding fungsi built-in.
Buka → # Bagian 5: Melakukan Join dan AgregasiGabungkan baris pesanan, header, dan dimensi produk, lalu ukur broadcast join melawan sort-merge join.
Buka → # Bagian 6: Mengatur PartitionAtur jumlah partition task dengan repartition dan coalesce, lalu kendalikan berkas yang dihasilkan saat menulis parquet.
Buka → # Bagian 7: Menganalisis Query PlanBaca physical plan mode formatted, simple, dan extended untuk memahami keputusan optimizer Catalyst.
Buka → # Bagian 8: Mengoptimalkan JobUkur dampak cache, column pruning, dan predicate pushdown dengan angka nyata dari mesin uji dua CPU.
Buka → # Bagian 9: Menyimpan HasilTulis hasil agregat sebagai parquet partition by bulan, verifikasi baca ulang, dan pastikan pipeline idempoten.
Buka →