Delta Lake dan Iceberg sangat kuat untuk tabel yang diisi secara batch: append satu batch, satu commit. Namun banyak tabel sumber berbeda sifatnya — tabel pelanggan berubah beberapa baris setiap menit, aliran CDC database datang sebagai update dan penghapusan, dan sistem rekomendasi butuh data segar dalam hitungan menit. Apache Hudi adalah table format yang dirancang sejak awal untuk beban perubahan baris per baris tersebut. Chapter ini bersifat konseptual: tidak ada writer Hudi yang berjalan murni dari Python lokal, sehingga kita membedah struktur dan mekanismenya lewat prosa, tabel, dan sketsa kode.
Timeline sebagai Sumber Kebenaran #
Setiap perubahan pada tabel Hudi tercatat sebagai instant pada timeline — daftar aksi berurutan yang disimpan di direktori .hoodie. Satu aksi berjalan melalui beberapa status: requested (direncanakan), inflight (sedang berjalan), lalu selesai dengan ekstensi sesuai jenisnya. Struktur umum direktori tabel Hudi tampak seperti berikut — nama berkas memakai pola, dan penamaan persisnya mengikuti versi Hudi yang dipakai:
pesanan_hudi/
├── .hoodie/
│ ├── <instant>.commit (aksi COMMIT selesai: tabel COW)
│ ├── <instant>.deltacommit (aksi DELTA_COMMIT selesai: tabel MOR)
│ ├── <instant>.compaction.requested (kompaksi dijadwalkan)
│ ├── <instant>.clean.requested (pembersihan berkas lama dijadwalkan)
│ ├── <instant>.rollback.inflight (pembatalan commit berjalan)
│ └── hoodie.properties (identitas tabel: nama, tipe, basis data)
├── kota=Bandung/
│ ├── <fileId>_<writeToken>_<instant>.parquet (base file)
│ └── .<fileId>_<instant>.log.<token> (log file, khas MOR)
└── kota=Depok/
└── <fileId>_<writeToken>_<instant>.parquetJenis aksi yang paling sering muncul pada timeline:
| Aksi | Arti |
|---|---|
| COMMIT | penulisan selesai pada tabel Copy on Write |
| DELTA_COMMIT | penulisan selesai pada tabel Merge on Read (data masuk ke log file) |
| COMPACTION | penggabungan log file menjadi base file baru |
| CLEAN | penghapusan berkas lama yang sudah tidak dirujuk snapshot |
| ROLLBACK | pembatalan commit yang gagal, mengembalikan tabel ke keadaan sebelumnya |
Karena timeline adalah satu-satunya sumber kebenaran, pembaca menentukan isi snapshot dengan cara yang sama seperti Delta Lake membaca _delta_log — hanya bentuknya berbeda: kumpulan berkas berstatus selesai, bukan satu berkas JSON bernomor.
File Group dan Index #
Kekuatan utama Hudi ada pada cara penulisan menemukan lokasi sebuah baris. Setiap baris punya record key (misal kolom id). Hudi memelihara index yang memetakan record key ke file group — kelompok berkas yang menampung baris tersebut. Saat sebuah update datang untuk pelanggan id=1, index langsung menunjuk file group tempat baris itu berada, sehingga Hudi cukup menulis ulang file group bersangkutan tanpa memindai seluruh tabel. Inilah yang membuat upsert tingkat record menjadi murah, sesuatu yang pada Delta atau Iceberg klasik biasanya harus dikerjakan lewat pernyataan MERGE yang membaca lebih banyak data.
Satu file group terdiri atas beberapa file slice: base file Parquet untuk suatu rentang waktu, ditambah log file yang menampung perubahan setelahnya. Index yang umum dipakai antara lain bloom filter, simple index, dan index berbasis HBase untuk tabel sangat besar.
COW vs MOR #
Hudi menawarkan dua tipe tabel yang menukar biaya antara penulisan dan pembacaan:
| Aspek | Copy on Write (COW) | Merge on Read (MOR) |
|---|---|---|
| Update baris | menulis ulang base file Parquet baru | menambah record ke log file |
| Penghapusan baris | menulis ulang base file tanpa baris itu | menandai penghapusan di log file |
| Latensi penulisan | lebih tinggi (rewrite penuh file) | rendah — append ke log |
| Kecepatan pembacaan | tinggi — langsung membaca Parquet | lebih lambat — perlu menggabung base dan log |
| Kapan dikompaksi | tidak diperlukan | berkala; COMPACTION mengubah log menjadi base file |
| Cocok untuk | analitik batch, beban baca dominan | near-real-time, update frekuen |
Pilihan tipe tabel adalah keputusan arsitektural: COW memindahkan beban ke saat menulis, MOR menundanya ke saat membaca lalu membayarnya kembali lewat kompaksi berkala.
Sketsa Penulisan di Spark #
Sketsa berikut memperlihatkan opsi-opsi inti saat menulis tabel Hudi dari Spark. Opsi hoodie.datasource.write.* mengatur identitas tabel, record key, kolom precombine, dan partisi — keempatnya adalah kontrak minimum yang harus ditentukan penulis:
# Sketsa konseptual — tidak dieksekusi di bab ini.
# Menjalankan Hudi membutuhkan runtime Spark plus bundel jar Hudi
# (sesuaikan artefak dengan versi Spark dan Hudi Anda).
from pyspark.sql import SparkSession
spark = (
SparkSession.builder
.master("local[1]")
.config("spark.ui.enabled", "false")
.config("spark.jars.packages", "org.apache.hudi:hudi-spark<versi-spark>:<versi-hudi>")
.appName("contoh-hudi")
.getOrCreate()
)
pesanan = spark.createDataFrame(
[
(1, "Budi", "Bandung"),
(2, "Siti", "Depok"),
],
"id INT, nama STRING, kota STRING",
)
(
pesanan.write.format("hudi")
.option("hoodie.table.name", "pesanan_hudi")
.option("hoodie.table.type", "MERGE_ON_READ")
.option("hoodie.datasource.write.operation", "upsert")
.option("hoodie.datasource.write.recordkey.field", "id")
.option("hoodie.datasource.write.precombine.field", "nama")
.option("hoodie.datasource.write.partitionpath.field", "kota")
.mode("append")
.save("file:///tmp/hudi/pesanan")
)Tiga opsi paling menentukan: recordkey.field menjadi kunci index, precombine.field menyebut kolom versi yang dipakai Hudi untuk memilih baris terbaru ketika record key yang sama datang lebih dari sekali, dan partitionpath.field menentukan direktori partisi tempat file group berada. Operasi upsert berarti update dan penyisipan ditangani satu jalur; operasi lain yang tersedia antara lain insert, bulk_insert, dan delete.
Kapan Hudi Unggul #
- Update dan penghapusan datang terus-menerus dari CDC database — Hudi mengubahnya menjadi tabel tanpa menulis ulang tabel penuh.
- Latensi penyegaran harus rendah (menit, bukan jam) — MOR menerima update ke log file tanpa menunggu kompaksi.
- Satu tabel menerima tulisan dari banyak pekerjaan — timeline dan rollback bawaan menjaga konsistensi.
- Baca dominan tetap dihargai — pilih COW dan pembaca tetap membaca Parquet final tanpa penggabungan.
Posisi di Ekosistem #
Ketiga table format utama berasal dari masalah yang berbeda di perusahaan yang berbeda:
| Format | Diciptakan di | Masalah asal | Kekuatan khas |
|---|---|---|---|
| Apache Iceberg | Netflix | tabel Hive yang rapuh pada perubahan cepat | metadata berlapis, partition evolution |
| Delta Lake | Databricks | transaksi ACID di object storage | log JSON sederhana, ekosistem Databricks |
| Apache Hudi | Uber | data freshness di tabel yang berubah terus | upsert tingkat record, timeline |
Hudi bermula di Uber sekitar tahun 2016 untuk mempercepat penyegaran data, kemudian menjadi project Apache. Versi stabilnya saat riset course ini adalah Hudi 1.x dengan rilis 1.0 pada akhir 2024. Di sisi engine, Hudi didukung Spark dan Flink secara bawaan, sementara Trino dan Hive membaca tabel Hudi melalui konektor resmi — rujukan lengkapnya ada di dokumentasi Apache Hudi .
Setelah mengenal tiga table format, pertanyaan berikutnya menyangkut pintu masuknya: apa yang terjadi jika data yang masuk tidak sesuai schema tabel? Pertanyaan itu dijawab pada Chapter Schema Enforcement.