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:

text
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>.parquet

Jenis aksi yang paling sering muncul pada timeline:

AksiArti
COMMITpenulisan selesai pada tabel Copy on Write
DELTA_COMMITpenulisan selesai pada tabel Merge on Read (data masuk ke log file)
COMPACTIONpenggabungan log file menjadi base file baru
CLEANpenghapusan berkas lama yang sudah tidak dirujuk snapshot
ROLLBACKpembatalan 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:

AspekCopy on Write (COW)Merge on Read (MOR)
Update barismenulis ulang base file Parquet barumenambah record ke log file
Penghapusan barismenulis ulang base file tanpa baris itumenandai penghapusan di log file
Latensi penulisanlebih tinggi (rewrite penuh file)rendah — append ke log
Kecepatan pembacaantinggi — langsung membaca Parquetlebih lambat — perlu menggabung base dan log
Kapan dikompaksitidak diperlukanberkala; COMPACTION mengubah log menjadi base file
Cocok untukanalitik batch, beban baca dominannear-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:

python
# 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:

FormatDiciptakan diMasalah asalKekuatan khas
Apache IcebergNetflixtabel Hive yang rapuh pada perubahan cepatmetadata berlapis, partition evolution
Delta LakeDatabrickstransaksi ACID di object storagelog JSON sederhana, ekosistem Databricks
Apache HudiUberdata freshness di tabel yang berubah terusupsert 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.