10 poin oleh GN⁺ 2025-12-16 | Belum ada komentar. | Bagikan ke WhatsApp
  • UUID v4 memiliki tingkat keacakan yang tinggi sehingga memicu inefisiensi indeks dan I/O berlebihan, dan jika digunakan sebagai kunci utama di PostgreSQL dapat menurunkan performa
  • Karena penyisipan berlangsung secara acak, page split dan fragmentasi indeks lebih sering terjadi, serta menyebabkan ukuran log WAL membesar dan latensi tulis meningkat
  • UUID berukuran 16 byte, dua kali lebih besar daripada bigint, yang berujung pada penurunan cache hit ratio dan pemborosan memori
  • Sering disalahpahami sebagai pengenal yang aman, tetapi menurut RFC 4122, UUID bukan sarana keamanan untuk mencegah tebakan
  • Untuk database baru, disarankan menggunakan kunci berbasis sequence bertipe integer, dan bila tak terhindarkan, gunakan UUID v7 yang berurutan berdasarkan waktu

Masalah performa UUID v4

  • Database PostgreSQL yang menggunakan kunci utama UUID v4 selama 10 tahun terakhir secara konsisten menunjukkan penurunan performa dan I/O berlebihan
    • UUID v4 menghasilkan 122 bit acak sehingga indeks tidak bisa diurutkan
    • Saat penyisipan, data tidak disimpan ke halaman yang berurutan sehingga terjadi akses acak, dan saat update maupun delete juga diperlukan penelusuran yang tidak efisien
  • Indeks B-Tree mengasumsikan data terurut, tetapi UUID v4 tidak memiliki keterurutan sehingga efisiensi insert rendah
    • Setiap insert ditulis ke halaman acak sehingga page split di tengah sering terjadi
    • Akibatnya muncul latensi tulis dan peningkatan WAL

Struktur UUID dan alternatifnya

  • UUID adalah pengenal berukuran 128 bit (16 byte), dan di PostgreSQL disimpan sebagai tipe binary uuid
  • UUID v4 berbasis bit acak, sedangkan UUID v7 menyertakan timestamp pada 48 bit pertama sehingga efisiensi indeks lebih baik
  • PostgreSQL 18 (direncanakan pada 2025) akan mendukung UUID v7 secara bawaan
  • UUID v7 dapat diurutkan secara kronologis sehingga kepadatan halaman dan efisiensi cache meningkat

Alasan memilih UUID dan keterbatasannya

  • UUID digunakan saat dibutuhkan pembuatan pengenal tanpa benturan di lingkungan multi-klien atau microservices
    • Contoh: membuat ID secara bersamaan di beberapa instance database
  • Namun, RFC 4122 menyatakan “jangan menganggap UUID sulit ditebak”, sehingga tidak cocok sebagai pengenal keamanan
  • Probabilitas benturan mencapai 50% setelah menghasilkan 2.71×10¹⁸ UUID; dalam praktiknya peluang benturan rendah, tetapi biaya performanya tinggi

Inefisiensi ruang dan I/O pada UUID

  • UUID memakan ruang dua kali lipat dari bigint (8 byte) dan empat kali lipat dari int (4 byte)
    • Pada tabel besar, hal ini menyebabkan kebutuhan penyimpanan meningkat serta waktu backup dan restore bertambah
  • Hasil eksperimen kepadatan halaman indeks
    • indeks integer: 97.64%
    • indeks UUID v4: 79.06%
    • indeks UUID v7: 90.09%
  • Dalam pengujian Cybertec, pencarian pada indeks UUID v4 membutuhkan tambahan 8.5 juta akses halaman, dengan I/O naik 31229%
    • Dalam kondisi yang sama, indeks bigint membutuhkan 27,332 akses buffer, sedangkan UUID v4 membutuhkan 8,562,960 akses buffer

Dampak pada cache dan memori

  • Karena distribusinya acak, UUID memiliki buffer cache hit ratio yang rendah
    • Lebih banyak halaman harus dimuat ke cache, dan halaman yang dibutuhkan lebih sering mengalami eviction
  • Penurunan efisiensi cache menimbulkan latensi query dan kenaikan penggunaan memori
  • Untuk menjaga performa, disarankan melakukan rekonstruksi indeks berkala (REINDEX CONCURRENTLY) atau menggunakan pg_repack

Cara mengurangi dampak performa

  • Menambah memori: disarankan menyediakan RAM 4 kali ukuran database (contoh: DB 25GB → memori 128GB)
  • Menyesuaikan work_mem: performa dapat meningkat dengan mengalokasikan lebih banyak memori untuk operasi sort
  • Di lingkungan Rails, gunakan pengaturan implicit_order_column agar memakai kolom yang bisa diurutkan seperti created_at, bukan UUID
  • Dengan perintah CLUSTER, tabel dapat ditata ulang berdasarkan kolom yang bisa diurutkan, tetapi memerlukan exclusive lock

Rekomendasi kunci integer dan sequence

  • Untuk database baru, disarankan memakai kunci berbasis sequence bertipe integer
    • integer (4 byte) menyediakan sekitar 2 miliar nilai unik, sedangkan bigint (8 byte) menyediakan jauh lebih banyak
  • Sebagian besar aplikasi bisnis sudah cukup dengan integer, sementara layanan berskala besar lebih cocok menggunakan bigint
  • Sebagai alternatif yang realistis selain UUID v4, gunakan UUID v7 atau ekstensi sequential_uuids

Ringkasan

  • UUID v4 menyebabkan inefisiensi indeks, I/O tinggi, dan efisiensi cache rendah karena sifatnya yang acak
  • UUID v4 tidak dapat digunakan sebagai pengenal keamanan dan juga boros ruang
  • Kunci sequence bertipe integer lebih cocok untuk sebagian besar aplikasi
  • Jika UUID memang harus digunakan, pilih UUID v7 yang berurutan berdasarkan waktu
  • Sebaiknya hindari penggunaan gen_random_uuid() sebagai kunci utama di PostgreSQL

Belum ada komentar.

Belum ada komentar.