Perbandingan Menyeluruh UUID v4 / UUID v7 / ULID: cara memilih berdasarkan kronologi, efisiensi, dan keterbacaan
UUID dan ULID adalah mekanisme untuk menerbitkan “ID unik” di dalam sistem terdistribusi maupun basis data. Sekilas formatnya serupa, tetapi ada perbedaan dalam aspek standardisasi, efisiensi penyimpanan, keterbacaan oleh manusia, hingga risiko kebocoran informasi. Tulisan ini merangkum karakteristik serta panduan memilih tiga opsi populer — UUID v4, UUID v7, dan ULID — dan menutupnya dengan catatan tambahan mengenai UUID v1 / v6.
Jika Anda memerlukan alat yang seluruh prosesnya berjalan di dalam peramban untuk membuat dan membaca masing-masing ID beserta informasi waktunya, silakan gunakan daftar berikut.
- Generator UUIDv4
- Generator UUIDv7
- Pembaca informasi waktu UUIDv7
- Generator ULID
- Pembaca informasi waktu ULID
UUID v4: tipe acak sepenuhnya
UUID v4 menggunakan 122 bit dari total 128 bit sebagai angka acak, sehingga probabilitas tabrakannya amat kecil. Sebaliknya, nilai tersebut tidak tersusun secara kronologis, sehingga indeks B-Tree kerap mengalami pemisahan halaman dan locality penyisipannya menjadi buruk. ID ini cocok untuk skenario seperti ID sesi atau kunci satu kali ketika “benar-benar acak” sudah memadai.
UUID v7: evolusi resmi yang dapat diurutkan kronologis
UUID v7 yang distandardisasi pada tahun 2024 melalui RFC 9562 menempatkan 48 bit terdepan sebagai waktu UNIX epoch dalam milidetik, sementara sisanya diisi angka acak. Perbandingan secara leksikografis (string) menjadi identik dengan urutan pembuatan (kronologi), sehingga tetap menjaga locality indeks meski dijadikan kunci utama. Kelebihan lain: formatnya dapat langsung disimpan pada tipe uuid
atau BINARY(16)
yang sudah ada.
- Tentang panjang bit acak: setelah mengabaikan beberapa bit untuk version/variant, UUID v7 memanfaatkan sekitar 74 bit sebagai angka acak. Sejumlah implementasi menerapkan monotonic generation (penyesuaian ulang sebagian angka acak untuk mencegah tabrakan dalam milidetik yang sama), tetapi secara statistik entropinya tetap mencukupi.
- Risiko kebocoran informasi: dari sebuah ID, waktu pembuatan (ketelitian ms) dapat diduga. Jika volume penerbitan tinggi dan implementasi angkanya lemah, ada kemungkinan ID di sekitarnya relatif mudah ditebak. Dalam sistem internal biasanya dapat diterima, tetapi untuk endpoint publik yang menghindari ekspose pola penomoran, hal ini perlu dipertimbangkan.
ULID: ID yang ramah manusia
ULID adalah standar de facto yang diperkenalkan pada 2016, menggunakan 26 karakter Crockford Base32. Karakter yang mudah keliru (O/I/L/1) dihilangkan sehingga nyaman untuk ditempel di URL maupun disalin. Sama seperti UUID v7, ULID juga menyimpan waktu (ms) pada 48 bit pertama, sehingga urutan leksikografis string = urutan kronologis.
- Jaminan pengurutan: perbandingan leksikografis antara string Base32 ULID selalu mencerminkan urutan kronologis (fitur monotonic generation juga luas diadopsi).
- Cara penyimpanan: format
TEXT(26)
memberi keterbacaan yang baik, namun jika ingin menyimpan dalam bentuk biner diperlukan konversi Base32↔16 byte. Meskipun dapat diperlakukan sebagai biner 128 bit, format ini sering kali tidak kompatibel dengan tipe khusus UUID di RDB. - Risiko kebocoran informasi: sama seperti v7, waktu (ms) terekspos. Untuk ID sumber daya API publik yang “tidak ingin menunjukkan urutan penerbitan”, keputusan pemakaian harus hati-hati.
Perbandingan tiga pendekatan (perspektif praktis)
Aspek | UUID v4 | UUID v7 | ULID |
---|---|---|---|
Standardisasi | RFC 4122 | RFC 9562 (2024) | Non-standar (de facto) |
Komposisi bit | 122 bit acak dari total 128 bit | 48 bit = UNIX ms + sisa acak (dapat monotonic) |
48 bit = UNIX ms + 80 bit acak |
Entropi acak | ≈122 bit | ≈74 bit (perkiraan setelah version/variant) | 80 bit |
Representasi string | 36 karakter (heksadesimal + tanda hubung) | 36 karakter (heksadesimal + tanda hubung) | 26 karakter (Crockford Base32) |
Pengurutan alami (teks) | × (acak) | ○ (leksikografis = kronologis) | ○ (leksikografis = kronologis) |
Pengurutan alami (biner) | × | ○ (BINARY(16) dengan memcmp menaik) |
○ (memcmp menaik jika 6 byte waktu ditempatkan di awal dalam big-endian) |
Karakteristik penyimpanan DB | Optimal pada tipe uuid / BINARY(16) |
Optimal pada tipe uuid / BINARY(16) |
TEXT(26) mudah dibaca, BINARY(16) butuh konversi / tidak kompatibel dengan tipe UUID |
Locality indeks | Buruk (penyisipan acak memecah halaman) | Baik (append di ujung / waspada hotspot) | Baik (append di ujung / waspada hotspot) |
Biaya pencarian kesetaraan | Rendah (perbandingan 16 byte) | Rendah (perbandingan 16 byte) | TEXT sedikit lebih mahal (dipengaruhi collation) / BINARY rendah |
Beban enkode | heksadesimal↔16 byte (ringan) | heksadesimal↔16 byte (ringan) | Base32↔16 byte (sedikit lebih berat) |
Keterbacaan manusia / cocok untuk URL | Rendah | Rendah | Tinggi |
Informasi terekspos (waktu pembuatan) | Tidak ada | Ada (ms) | Ada (ms) |
Penggunaan utama | ID sesi, kunci satu kali | Kunci utama DB, ID event, log kronologis | URL / ID publik, visibilitas log |
Catatan (hotspot v7/ULID): jika penyisipan append menumpuk pada satu shard atau satu pemimpin replika, ujung B-Tree dapat menjadi hotspot. Pertimbangkan teknik seperti shuffle kecil pada bit atas (“prefix shuffle”) atau mengombinasikan kunci sharding sebagai mitigasi.
Catatan implementasi DB (PostgreSQL / MySQL / SQLite)
- PostgreSQL
- v4/v7: tipe
uuid
adalah pilihan terbaik. Untuk v7, masukkan string keuuid
agar tetap menikmati sifat pengurutan. - ULID: gunakan
char(26)
/text
ataubytea(16)
(dengan konversi Base32).
- v4/v7: tipe
- MySQL/InnoDB
BINARY(16)
paling cepat dan hemat ruang (v4/v7). v7 mempertahankan pengurutan kronologis dengan perbandingan big-endian apa adanya. ULID dapat memakaiCHAR(26)
atauBINARY(16)
+ konversi.
- SQLite
- Tidak memiliki tipe khusus UUID. Gunakan
BLOB(16)
atauTEXT
. BLOB yang terindeks relatif efisien untuk perbandingan.
- Tidak memiliki tipe khusus UUID. Gunakan
Penguatan dari sudut pandang keamanan
- Ketahanan terhadap tebakan: karena v7/ULID berbagi bit waktu, jika banyak ID diterbitkan dalam milidetik yang sama dan PRNG-nya lemah, risiko penebakan ID di sekitar akan naik. Gunakan PRNG kriptografis dan minimalkan bias akibat increment monotonic.
- Kebocoran metadata: dari sebuah ID, waktu pembuatan dan perkiraan volume terbit dapat disimpulkan. Untuk API publik, desain yang memisahkan ID internal dan ID yang dipublikasikan lebih aman.
Ringkasan panduan pemilihan
- UUID v4: sepenuhnya acak. Tidak memiliki sifat pengurutan. Risiko tabrakan teoretis sangat kecil namun tidak nol. Cocok untuk ID sesi atau token CSRF.
- UUID v7: UUID berurutan yang sudah distandardisasi. Paling ideal untuk sistem internal dan kunci utama DB. Monotonic generation membuat risiko tabrakan praktis hilang.
- ULID: relatif lebih ramah manusia. Jika keterbacaan URL atau visibilitas log penting, ini kandidat kuat, tetapi untuk kunci utama internal biasanya v7 lebih unggul. Monotonic generation juga membuat risiko tabrakan praktis hilang.
Catatan tambahan: UUID v1 / v6 (singkat)
-
UUID v1 (berbasis waktu + MAC) Menggabungkan stempel waktu 60 bit (kelipatan 100 ns) dan pengenal node (sering berupa alamat MAC). Sifat kronologisnya kuat, tetapi informasi host dari MAC terekspos, dan ada banyak perhatian implementasi seperti penanganan clock rollback. Di masa kini sering tidak direkomendasikan karena alasan privasi.
-
UUID v6 (versi diurutkan ulang dari v1) Menata ulang stempel waktu v1 ke dalam big-endian agar mudah diurutkan leksikografis. Secara historis muncul sebagai “v1 yang lebih mudah diurutkan”, tetapi standardisasi kini condong ke v7. Untuk desain baru, biasanya v7 lebih dipilih daripada v6.
Lampiran: daftar periksa saat implementasi
- Pastikan sumber angka acak berasal dari PRNG kriptografis (sumber aman dari OS).
- Monotonic generation pada v7/ULID harus mencegah tabrakan dalam milidetik yang sama sembari menjaga bias angka acak serendah mungkin.
- Prioritaskan tipe
uuid
/BINARY(16)
pada basis data dan hindari degradasi kinerja akibat collation kolom string. - Tetapkan kebijakan ID publik (apakah ekspos urutan diperbolehkan). Jika perlu, pisahkan ID internal dan ID publik.
Pada akhirnya, secara teknis UUID v7 menjadi kandidat utama untuk kunci utama internal, sementara ULID layak dipertimbangkan bila keterbacaan pengguna atau kendala teknis tertentu memaksa. Hanya ketika ada kebutuhan khusus (misalnya pelarangan penuh terhadap ekspos waktu) barulah kita memilih v4 atau pendekatan lain.