Konteks dan cakupan
Sebuah tabel lake pesanan dibaca oleh pekerjaan batch, streaming, dan analis ad hoc. Bisnis menginginkan kolom bersarang (nested field), penggantian nama kolom, dan perubahan bertahap dari pemartisian bulanan ke harian. Pekerjaan lama tidak dapat ditingkatkan versinya sekaligus, dan menulis ulang semua file historis terlalu mahal. Jelaskan bagaimana Iceberg mencatat perubahan ini dan menjaga kebenaran pembaca saat tata letak lama dan baru hidup berdampingan.
Asumsikan sebuah Iceberg Catalog dan mesin eksekusi yang mendukung versi Iceberg yang dituju. Wawancara ini menguji evolusi skema dan partisi pada format tabel, bukan sintaks Spark SQL tertentu.
Hal yang dievaluasi pewawancara
- Apakah Anda membedakan antara field ID, Schema ID, Partition Spec ID, dan snapshot.
- Apakah Anda menjelaskan mengapa penambahan, penghapusan, penggantian nama, dan promosi tipe tertentu tidak perlu menulis ulang file lama, beserta batasannya.
- Apakah Anda menjelaskan koeksistensi tata letak partisi dan perencanaan kueri di berbagai spesifikasi, termasuk kapan penulisan ulang masih bermanfaat.
- Apakah Anda mengusulkan validasi kompatibilitas, performa, commit bersamaan (concurrent-commit), dan rollback.
Pertanyaan untuk diklarifikasi terlebih dahulu
- Apakah pembaca menggunakan format tabel Iceberg, atau sekadar memperlakukan direktori sebagai tabel Hive? Yang terakhir tidak secara otomatis menyediakan semantik field-ID.
- Apakah perubahan berada pada tingkat atas (top-level), bersarang, atau transformasi partisi? Kolom bersarang dan partisi memiliki batasan ekstra.
- Apakah pembaca lama mengikat kolom berdasarkan posisi atau menyimpan cache skema lama? Konfirmasikan bahwa mesin eksekusi mematuhi pemetaan field Iceberg.
- Apakah tujuannya untuk mengurangi pemindaian, memperbaiki hotspot, atau hanya perubahan skema logis? Manfaat partisi memerlukan bukti kueri.
Kerangka jawaban 30 detik
“Iceberg menyimpan status tabel dalam metadata berversi dan memetakan kolom dengan field ID yang tidak digunakan kembali, alih-alih menggunakan posisi atau nama daur ulang. Perubahan skema membuat Schema ID; perubahan partisi membuat Partition Spec ID. File lama mempertahankan tata letaknya, penulisan baru menggunakan spesifikasi baru, dan pembaca merencanakan setiap spesifikasi sambil menggunakan hidden partition pruning. Saya akan menjalankan pemeriksaan kompatibilitas, memublikasikan metadata secara atomik, lalu menguji pembaca lama dan baru, kebenaran penggantian nama, file yang dipindai, kegagalan percobaan ulang, dan rollback snapshot. ‘Tanpa penulisan ulang file’ adalah properti migrasi, bukan janji nol biaya performa.”
Analisis langkah demi langkah
1. Gunakan field ID untuk identitas kolom
Iceberg menetapkan ID untuk setiap field yang tidak pernah digunakan kembali dalam sebuah tabel. Penggantian nama mengubah namanya sementara pembaca tetap menemukan field asli berdasarkan ID. Menambahkan kembali nama yang telah dihapus akan mendapatkan ID baru, sehingga nilai dari file lama tidak dapat muncul kembali secara diam-diam. Format berbasis posisi tidak dapat menangani penghapusan dan penyusunan ulang dengan aman; penggunaan kembali nama juga dapat salah memetakan data.
Old schema: id=17, name="customer_id"
New schema: id=17, name="account_id"
Added field: id=42, name="region"2. Pisahkan Schema ID dari field ID
Sebuah field ID menjawab "kolom mana ini?" Sebuah Schema ID menjawab "versi struktur tabel mana ini?" Sebuah evolusi membuat objek skema baru dan menjadikan Schema ID-nya sebagai yang terkini; snapshot mencatat skema yang digunakan saat ditulis. Pembaca tidak dapat dengan aman mengandalkan array nama kolom yang di-cache.
3. Tentukan perubahan skema mana yang aman
Operasi penambahan, penghapusan, penggantian nama, penyusunan ulang, dan pelebaran tipe tertentu didukung, tetapi tidak semua perubahan tipe aman. Periksa versi format, rentang nilai, dan transformasi partisi. Kolom yang digunakan oleh transformasi bucket mungkin tidak dapat dipromosikan jika hasil transformasinya berubah. Perubahan struktural map-key juga memiliki batasan kesetaraan.
Safe candidate: add an optional field, rename a non-partition field, int -> long when transform output is unchanged
Block or redesign: narrowing a type, changing bucket input semantics, dropping a field required by critical readers4. Biarkan spesifikasi partisi lama dan baru berdampingan
Evolusi partisi membuat Partition Spec ID baru. File lama mempertahankan spesifikasi lama sedangkan file baru menggunakan default yang baru. Pembaca harus menginterpretasikan setiap file menggunakan spesifikasinya dan menggabungkan hasilnya. Pemartisian tersembunyi (hidden partitioning) memungkinkan kueri mengekspresikan predikat pada nilai data alih-alih melakukan hard-coding direktori tanggal.
5. Evaluasi "tanpa penulisan ulang" terhadap performa kueri
Evolusi metadata menghindari penulisan ulang file data sehingga menurunkan biaya migrasi, tetapi file lama tetap memiliki tata letak fisik lama. Beberapa spesifikasi dapat membuat beberapa rencana pemisahan (split plans) dengan kualitas pemangkasan yang berbeda. Bandingkan file yang dipindai, waktu perencanaan, byte yang dibaca, task skew, dan jumlah file kecil. Jika tata letak lama tetap menjadi hotspot, jadwalkan penulisan ulang yang terikat daripada berpura-pura bahwa evolusi logis telah mengatur ulang data fisik.
6. Lindungi publikasi dengan commit atomik dan snapshot
Status tabel direpresentasikan oleh file metadata dan snapshot; pembaruan secara atomik menggantikan penunjuk metadata saat ini. Baca versi saat ini, bangun metadata baru darinya, dan lakukan commit. Jika terjadi konflik, segarkan dan coba lagi. Kaitkan catatan perubahan ke snapshot ID sehingga peluncuran yang bermasalah dapat kembali ke snapshot yang terverifikasi sambil mempertahankan jendela kompatibilitas untuk pembaca lama.
Contoh jawaban berkualitas tinggi
Saya akan memisahkan identitas kolom, versi struktural, dan tata letak fisik. Field ID mencegah penggantian nama atau penyusunan ulang dari pemetaan nilai file lama yang salah; Schema ID mencatat versi struktural; Partition Spec ID mencatat transformasi partisi. Menambahkan region atau mengganti nama customer_id adalah pekerjaan metadata, bukan penulisan ulang file, tetapi saya akan memverifikasi terlebih dahulu bahwa setiap mesin eksekusi membaca berdasarkan field ID.
Untuk pemartisian bulanan ke harian, saya akan membuat spesifikasi baru dan menggunakannya untuk penulisan baru sambil mempertahankan spesifikasi lama pada file yang ada. Perencana harus menerapkan ekspresi partisi setiap spesifikasi dan menggabungkan pemisahannya. Sebelum memublikasikan, saya akan menjalankan matriks pembaca lama/pembaca baru, membandingkan nilai di seluruh penggantian nama, mengukur file dan byte yang dipindai, serta melakukan commit dari cabang terisolasi atau transaksi katalog. Jika konflik atau regresi kueri muncul, lakukan rollback berdasarkan snapshot; jika tata letak lama tetap lambat, jalankan penulisan ulang yang dianggarkan nanti.
Kesalahan umum dan perbaikan
- Kesalahan → Memperlakukan penggantian nama kolom sebagai perubahan posisi file → Mengapa gagal → Pengikatan posisi dapat melampirkan nilai yang salah → Perbaikan → Jelaskan identitas field yang stabil dan verifikasi pemetaan mesin.
- Kesalahan → Hanya memindai direktori baru setelah evolusi partisi → Mengapa gagal → File lama tetap menjadi bagian dari tabel dan hasilnya bisa tidak lengkap → Perbaikan → Pertahankan setiap Partition Spec dan gunakan perencanaan berbasis spesifikasi.
- Kesalahan → Menganggap "tanpa penulisan ulang" sebagai "tanpa biaya performa" → Mengapa gagal → Beberapa split dan tata letak lama masih dapat meningkatkan pemindaian → Perbaikan → Ukur perencanaan, file, byte, dan skew; tulis ulang dalam batch yang terkontrol jika diperlukan.
- Kesalahan → Menimpa metadata saat ini secara langsung → Mengapa gagal → Commit atau percobaan ulang yang bersamaan dapat kehilangan pembaruan → Perbaikan → Lakukan commit secara atomik dari versi yang dibaca, segarkan saat terjadi konflik, dan pertahankan titik rollback.
Pertanyaan lanjutan dan tanggapan
Mengapa Anda tidak dapat menghapus kolom lalu menggunakan kembali nama yang sama?
Anda dapat menambahkan nama itu lagi, tetapi harus menerima field ID baru. Menggunakan kembali ID lama dapat membuat nilai dari file lama muncul sebagai kolom baru, melanggar semantik penghapusan (drop). Uji file lama, file baru, dan ID yang ditetapkan ke nama yang dibuat ulang.
Apakah promosi int ke long selalu aman?
Tidak. Periksa versi format, rentang nilai, tipe downstream, dan apakah field tersebut menjadi sumber transformasi partisi. Jika bucket atau transformasi lain mengubah keluarannya, semantik partisi lama dan baru dapat menyimpang; blokir perubahan tersebut atau rancang spesifikasi baru terlebih dahulu.
Bisakah file lama bulanan dan file baru harian menyebabkan baris terlewat?
Tidak dalam implementasi yang benar. Pembaca menginterpretasikan setiap file dengan Partition Spec-nya, memangkas dalam spesifikasi tersebut, dan menggabungkan hasilnya. Uji kueri rentang yang melintasi batas evolusi dan bandingkan set baris dengan referensi pemindaian penuh.
Kapan Anda masih perlu menulis ulang file data?
Tulis ulang ketika tata letak lama menyebabkan pemindaian terus-menerus, skew, file kecil, atau biaya penyimpanan. Evolusi metadata skema atau partisi itu sendiri tidak memerlukannya. Berikan snapshot, kontrol konkurensi, dan anggaran pada penulisan ulang sehingga pembersihan fisik tetap dapat dibatalkan (reversible).