21 poin oleh GN⁺ 2024-07-06 | 4 komentar | Bagikan ke WhatsApp
  • UUID sering digunakan sebagai kunci utama tabel database
    • Mudah dibuat, mudah dibagikan antar sistem terdistribusi, dan menjamin keunikan
    • Jika mempertimbangkan ukuran UUID, wajar untuk bertanya apakah ini pilihan yang tepat, tetapi sering kali kita tidak bisa menentukan sendiri
  • Tulisan ini tidak berfokus pada pertanyaan "apakah UUID format yang cocok untuk key", melainkan menjelaskan cara menggunakan UUID secara efisien sebagai kunci utama di PostgreSQL

Menggunakan PostgreSQL dan UUID sebagai kunci utama

  • Apa itu UUID?
    • UUID sering digunakan sebagai kunci utama tabel database
    • Dapat dengan mudah dibagikan antar sistem terdistribusi dan menjamin keunikan
    • Karena ukurannya, kita bisa meragukan apakah UUID cocok, tetapi sering kali tidak ada banyak pilihan

Tipe data UUID di PostgreSQL

  • Menyimpan UUID sebagai string

    • PostgreSQL menyediakan tipe data text untuk menyimpan string
    • Namun, tipe text tidak cocok untuk menyimpan UUID
    • PostgreSQL menyediakan tipe data khusus uuid untuk UUID
    • Tipe uuid adalah tipe data 128-bit, dan membutuhkan 16 byte untuk menyimpan satu nilai
    • Tipe text menambahkan overhead 1 atau 4 byte
  • Hasil eksperimen

    • Membuat dua tabel untuk dibandingkan: satu menggunakan tipe text, satu lagi menggunakan tipe uuid
    • Setelah memasukkan 10.000.000 baris, ukuran tabel dan ukuran indeks dibandingkan
    • Tabel yang menggunakan tipe text 54% lebih besar, dan ukuran indeksnya 85% lebih besar

UUID dan indeks B-Tree

  • Indeks B-Tree dan UUID

    • UUID acak tidak cocok untuk indeks B-Tree
    • Indeks B-Tree bekerja baik dengan nilai yang berurutan
    • UUID.randomUUID() di Java mengembalikan UUID v4, yang merupakan nilai pseudo-acak
    • UUID v7 menghasilkan nilai yang terurut berdasarkan waktu, sehingga lebih cocok untuk indeks B-Tree
  • Menggunakan UUID v7

    • Untuk menggunakan UUID v7 di Java, dibutuhkan library java-uuid-generator
    • Menghasilkan UUID v7 dapat meningkatkan performa insert

Dampak UUID v7 terhadap performa INSERT

  • Eksperimen
    • Membuat tabel yang menggunakan UUID v7, lalu memasukkan 10.000 baris sebanyak 10 kali untuk mengukur performa
    • Hasilnya agak acak, tetapi memasukkan UUID v7 sekitar 2 kali lebih cepat

Bacaan tambahan

  • Ada kemungkinan UUID v7 akan didukung secara native di PostgreSQL 17
  • Informasi tentang format UUID v7
  • Dampak UUID terhadap performa sebagai kunci utama database

Ringkasan

  • Masalah panjang UUID

    • Sekalipun sudah dioptimalkan, UUID tetap bukan tipe yang paling ideal sebagai kunci utama
    • Jika punya pilihan, pertimbangkan opsi lain seperti TSID
  • Perlunya optimasi

    • Jika mengharapkan dataset besar atau traffic tinggi, optimasi perlu dipertimbangkan
    • Mengubah kunci utama adalah pekerjaan yang sulit, jadi penting untuk menetapkannya dengan benar sejak awal
  • Catatan

    • Penulis bukan ahli PostgreSQL, hanya membagikan apa yang dipelajari
    • Jika bermanfaat, penulis berharap mendapatkan masukan lewat komentar atau Twitter

Ringkasan GN⁺

  • Tulisan ini membahas cara yang efisien menggunakan UUID sebagai kunci utama di PostgreSQL
  • Melalui eksperimen, ditunjukkan bahwa penggunaan UUID v7 dapat meningkatkan performa insert
  • Jika mengharapkan dataset besar atau traffic tinggi, optimasi diperlukan
  • Opsi lain seperti TSID juga layak dipertimbangkan

4 komentar

 
savvykang 2024-07-09

Apakah terlalu berlebihan jika mengharapkan encoding base62 alih-alih format standar UUID (heksadesimal + tanda hubung)?

 
qurare 2024-07-08

uuidv7 itu tak tertandingi
uuidv8+ adalah "dewa"

 
bbulbum 2024-07-08

Hambatan terbesar adalah, ini tidak ramah bagi manusia.. Saya masih merasa bagian ini diperlukan di banyak aspek..

 
GN⁺ 2024-07-06
Opini Hacker News
  • Merekomendasikan penggunaan bigserial sebagai primary key yang ramah B-tree, dan mempertimbangkan UUID yang dienkode sebagai string sebagai opsi locator record eksternal

    • Jika akan dikutip oleh pengguna nonteknis, pertimbangkan dulu opsi yang lebih sederhana seperti locator bergaya PNR
    • Jangan mencampur tipe PK di dalam skema layanan atau aplikasi
    • Saat menggunakan UUIDv7 sebagai pengenal unik, gunakan hanya untuk data yang memang memiliki timecode bawaan
    • Jangan gunakan hashids; tidak memiliki kualitas kriptografis dan tidak familier bagi orang kebanyakan
    • Saat encoding, jangan gunakan base64 atau alfabet yang mengandung tanda hubung
  • Saat merancang skema database, ingat prinsip pemisahan concern dan mechanical sympathy

  • Typed random ID milik Stripe sebenarnya tidak benar-benar acak

    • Mengandung metadata, timestamp yang disematkan, shard dan key referensi, informasi versi, dan lain-lain
    • Secara pribadi lebih menyukai locator bigserial+HMAC terenkripsi AES yang dienkode base58
  • Di Postgres, UUID acak bukan masalah besar

    • UUID (16 byte) memang lebih besar daripada serial (4 byte) atau bigserial (8 byte), tetapi pada level keseluruhan tabel ini bukan masalah besar
  • Sebelum mempertimbangkan serial vs. UUID acak vs. UUID berurutan di Postgres, masih banyak hal lain yang lebih perlu dikhawatirkan

  • Baru-baru ini memilih ULID sebagai PK Postgres, dan sangat terbantu oleh artikel ini: https://brandur.org/nanoglyphs/026-ids

  • Alasan menyukai ULID adalah karena kompatibel dengan tipe UUID, dan memiliki timestamp bawaan sehingga jika ID diurutkan, hasilnya juga akan mengikuti urutan timestamp

  • Akan bagus jika int64 juga dimasukkan dalam perbandingan agar overhead antara UUID dan pendekatan tradisional bisa dibandingkan

  • Performa insert adalah cara yang buruk untuk mengevaluasi performa

    • Performa B-Tree memang lebih baik saat insert, tetapi menjadi pertanyaan bagaimana hasilnya pada transaksi skala besar
  • Di SQLite, UUID4 lebih disukai karena kemungkinan benturan page cache selama penguncian transaksi lebih kecil

    • Ini mungkin juga berlaku serupa pada sistem Postgres
  • Lebih menyukai primary key integer auto-increment

    • Mudah dipahami dan sederhana untuk diurutkan
    • Dalam proyek batch berskala besar, bisa menyimpan primary key terakhir lalu mengambil semua yang lebih besar dari itu
  • Benchmark waktu insert UUIDv7 memasukkan waktu pembuatan UUID

    • Ingin melihat biaya pembaruan indeks saja dipisahkan secara terpisah
  • Kecil kemungkinan dukungan UUIDv7 akan masuk ke PostgreSQL 17

    • Commiter untuk pekerjaan terbaru telah dihapus, dan versi 17 sudah berada dalam status feature freeze
  • Mulai menggunakan python-ulid, dan ULID lebih unggul daripada UUID

  • Karena tautan standar UUID v7 sudah usang, rujuk RFC 9562: https://datatracker.ietf.org/doc/html/rfc9562