Tentang penggunaan PostgreSQL dan UUID sebagai kunci utama
(maciejwalkowiak.com)- 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
textuntuk menyimpan string - Namun, tipe
texttidak cocok untuk menyimpan UUID - PostgreSQL menyediakan tipe data khusus
uuiduntuk UUID - Tipe
uuidadalah tipe data 128-bit, dan membutuhkan 16 byte untuk menyimpan satu nilai - Tipe
textmenambahkan overhead 1 atau 4 byte
- PostgreSQL menyediakan tipe data
-
Hasil eksperimen
- Membuat dua tabel untuk dibandingkan: satu menggunakan tipe
text, satu lagi menggunakan tipeuuid - Setelah memasukkan 10.000.000 baris, ukuran tabel dan ukuran indeks dibandingkan
- Tabel yang menggunakan tipe
text54% lebih besar, dan ukuran indeksnya 85% lebih besar
- Membuat dua tabel untuk dibandingkan: satu menggunakan tipe
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
- Untuk menggunakan UUID v7 di Java, dibutuhkan library
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
Apakah terlalu berlebihan jika mengharapkan encoding base62 alih-alih format standar UUID (heksadesimal + tanda hubung)?
uuidv7 itu tak tertandingi
uuidv8+ adalah "dewa"
Hambatan terbesar adalah, ini tidak ramah bagi manusia.. Saya masih merasa bagian ini diperlukan di banyak aspek..
Opini Hacker News
Merekomendasikan penggunaan
bigserialsebagai primary key yang ramah B-tree, dan mempertimbangkan UUID yang dienkode sebagai string sebagai opsi locator record eksternalhashids; tidak memiliki kualitas kriptografis dan tidak familier bagi orang kebanyakanSaat merancang skema database, ingat prinsip pemisahan concern dan mechanical sympathy
Typed random ID milik Stripe sebenarnya tidak benar-benar acak
bigserial+HMACterenkripsi AES yang dienkode base58Di Postgres, UUID acak bukan masalah besar
serial(4 byte) ataubigserial(8 byte), tetapi pada level keseluruhan tabel ini bukan masalah besarSebelum mempertimbangkan
serialvs. UUID acak vs. UUID berurutan di Postgres, masih banyak hal lain yang lebih perlu dikhawatirkanBaru-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
int64juga dimasukkan dalam perbandingan agar overhead antara UUID dan pendekatan tradisional bisa dibandingkanPerforma insert adalah cara yang buruk untuk mengevaluasi performa
Di SQLite, UUID4 lebih disukai karena kemungkinan benturan page cache selama penguncian transaksi lebih kecil
Lebih menyukai primary key integer auto-increment
Benchmark waktu insert UUIDv7 memasukkan waktu pembuatan UUID
Kecil kemungkinan dukungan UUIDv7 akan masuk ke PostgreSQL 17
Mulai menggunakan
python-ulid, dan ULID lebih unggul daripada UUIDKarena tautan standar UUID v7 sudah usang, rujuk RFC 9562: https://datatracker.ietf.org/doc/html/rfc9562