17 Sep 2025·8 menit membaca

UUID vs bigint di PostgreSQL: memilih ID yang bisa diskalakan

UUID vs bigint di PostgreSQL: bandingkan ukuran indeks, urutan pengurutan, kesiapan sharding, dan bagaimana ID mengalir lewat API, web, dan aplikasi mobile.

UUID vs bigint di PostgreSQL: memilih ID yang bisa diskalakan

Mengapa pilihan ID lebih penting daripada yang terlihat

Setiap baris di tabel PostgreSQL butuh cara yang stabil untuk ditemukan lagi. Itu tugas ID: mengidentifikasi sebuah record secara unik, biasanya sebagai primary key, dan menjadi pengikat untuk relasi. Tabel lain menyimpannya sebagai foreign key, query melakukan join dengannya, dan aplikasi melewatkannya sebagai pegangan untuk “pelanggan itu”, “faktur itu”, atau “tiket dukungan itu”.

Karena ID muncul di mana-mana, pilihannya bukan sekadar detail database. Dampaknya muncul kemudian pada ukuran indeks, pola penulisan, kecepatan query, rasio hit cache, bahkan pekerjaan produk seperti analytics, impor, dan debugging. Itu juga memengaruhi apa yang Anda ekspose di URL dan API, serta seberapa mudah aplikasi mobile menyimpan dan menyinkronkan data dengan aman.

Sebagian besar tim biasanya membandingkan UUID vs bigint di PostgreSQL. Secara sederhana, Anda memilih antara:

  • bigint: angka 64-bit, sering dihasilkan oleh sequence (1, 2, 3...).
  • UUID: identifier 128-bit, sering terlihat acak, atau dihasilkan dengan cara berurutan waktu.

Tidak ada opsi yang selalu menang. Bigint cenderung kompak dan ramah terhadap indeks dan pengurutan. UUID cocok ketika Anda butuh ID unik global antar sistem, ingin ID publik yang lebih aman, atau mengharapkan data dibuat di banyak tempat (beberapa service, mobile offline, atau sharding di masa depan).

Aturan praktis: putuskan berdasarkan bagaimana data akan dibuat dan dibagikan, bukan hanya bagaimana disimpan hari ini.

Dasar-dasar Bigint dan UUID dalam istilah sederhana

Saat orang membandingkan UUID vs bigint di PostgreSQL, mereka memilih antara dua cara memberi nama baris: angka counter kecil, atau nilai lebih panjang yang unik secara global.

Sebuah bigint adalah integer 64-bit. Di PostgreSQL biasanya dihasilkan dengan identity column (atau pola serial yang lebih lama). Database menjaga sequence di belakang dan memberikan nomor berikutnya setiap kali Anda insert baris. Itu berarti ID cenderung 1, 2, 3, 4... dan seterusnya. Sederhana, mudah dibaca, dan ramah di tools serta laporan.

Sebuah UUID (Universally Unique Identifier) adalah 128 bit. Sering ditulis sebagai 36 karakter dengan tanda hubung, mis. 550e8400-e29b-41d4-a716-446655440000. Jenis yang umum:

  • v4: UUID acak. Mudah dibuat di mana saja, tapi tidak berurutan menurut waktu pembuatan.
  • v7: UUID berurutan waktu. Masih unik, tapi dirancang untuk meningkat seiring waktu.

Penyimpanan adalah salah satu perbedaan praktis pertama: bigint memakai 8 byte, sedangkan UUID memakai 16 byte. Perbedaan ukuran itu muncul di indeks dan bisa memengaruhi hit rate cache (database bisa menampung lebih sedikit entri indeks di memori).

Pikirkan juga di mana ID muncul di luar database. ID bigint pendek di URL dan mudah dibaca dari log atau tiket dukungan. UUID lebih panjang dan merepotkan diketik, tapi lebih sulit ditebak dan bisa dibuat di klien saat diperlukan.

Ukuran indeks dan pembengkakan tabel: apa yang berubah

Perbedaan praktis terbesar antara bigint dan UUID adalah ukuran. Bigint 8 byte; UUID 16 byte. Kedengarannya kecil sampai Anda ingat indeks mengulang ID Anda berkali-kali.

Indeks primary key Anda perlu tetap hot di memori agar terasa cepat. Indeks yang lebih kecil berarti lebih banyak bagian yang muat di shared buffers dan CPU cache, sehingga lookup dan join membutuhkan lebih sedikit pembacaan disk. Dengan primary key UUID, indeks biasanya terasa lebih besar untuk jumlah baris yang sama.

Pengaliannya adalah indeks sekunder. Di B-tree PostgreSQL, setiap entri indeks sekunder juga menyimpan nilai primary key (agar database bisa menemukan baris). Jadi ID yang lebih lebar memperbesar bukan hanya indeks primary, tapi juga setiap indeks lain yang Anda tambahkan. Jika Anda punya tiga indeks sekunder, tambahan 8 byte dari UUID muncul secara efektif di empat tempat.

Foreign key dan tabel join juga merasakan dampaknya. Setiap tabel yang merujuk ID Anda menyimpan nilai itu di baris dan indeksnya sendiri. Tabel join many-to-many bisa terdiri dari dua foreign key plus overhead kecil, jadi menggandakan lebar kunci bisa sangat memperbesar jejaknya.

Dalam praktiknya:

  • UUID biasanya memperbesar indeks primary dan sekunder, dan perbedaannya terkompaun saat Anda menambah lebih banyak indeks.
  • Indeks yang lebih besar berarti tekanan memori lebih tinggi dan lebih banyak pembacaan page di bawah beban.
  • Semakin banyak tabel yang merujuk kunci itu (events, logs, join tables), semakin penting perbedaan ukuran.

Jika sebuah user ID muncul di users, orders, order_items, dan audit_log, nilai yang sama disimpan dan diindeks di semua tabel itu. Memilih ID yang lebih lebar adalah keputusan penyimpanan sama pentingnya dengan keputusan ID.

Urutan sort dan pola penulisan: ID berurutan vs acak

Sebagian besar primary key PostgreSQL berada pada indeks B-tree. B-tree bekerja paling baik ketika baris baru mendarat di dekat akhir indeks, karena database bisa terus menambahkan dengan sedikit pengacakan.

ID berurutan: dapat diprediksi dan ramah penyimpanan

Dengan bigint identity atau sequence, ID baru meningkat seiring waktu. Insert biasanya mengenai bagian paling kanan indeks, sehingga halaman tetap padat, cache tetap hangat, dan PostgreSQL melakukan lebih sedikit pekerjaan ekstra.

Ini penting bahkan jika Anda tidak pernah menjalankan ORDER BY id. Jalur penulisan tetap harus menempatkan setiap kunci baru ke dalam indeks secara terurut.

UUID acak: sebaran lebih luas, churn lebih besar

UUID acak (umum pada UUIDv4) menyebarkan insert ke seluruh indeks. Itu meningkatkan kemungkinan page split, di mana PostgreSQL harus mengalokasikan halaman indeks baru dan memindahkan entri untuk memberi ruang. Hasilnya adalah amplifikasi tulis: lebih banyak byte indeks ditulis, lebih banyak WAL dihasilkan, dan sering lebih banyak pekerjaan latar (vacuum dan penanganan bloat).

UUID berurutan waktu mengubah cerita. UUID yang sebagian besar meningkat seiring waktu (seperti UUIDv7 atau skema berbasis waktu lain) mengembalikan banyak locality, sambil tetap berukuran 16 byte dan tetap terlihat seperti UUID di API Anda.

Perbedaan ini terasa terutama saat Anda punya tingkat insert tinggi, tabel besar yang tidak muat di memori, dan banyak indeks sekunder. Jika Anda sensitif terhadap lonjakan latensi tulis akibat page split, hindari ID yang sepenuhnya acak pada tabel dengan write-hot.

Contoh: tabel events sibuk yang menerima log dari aplikasi mobile sepanjang hari biasanya berjalan lebih mulus dengan kunci berurutan atau UUID berurutan waktu dibanding UUID v4 acak.

Dampak performa yang benar-benar terasa

Tambahkan pemeriksaan akses yang benar
Implementasikan validasi dan otorisasi tanpa bergantung pada ID yang susah ditebak.
Gunakan BP Editor

Sebagian besar perlambatan dunia nyata bukanlah “UUID itu lambat” atau “bigint itu cepat”. Yang penting adalah apa yang harus disentuh database untuk menjawab query Anda.

Rencana query terutama peduli apakah mereka bisa menggunakan index scan untuk filter, melakukan join cepat pada kunci, dan apakah tabel terurut secara fisik (atau cukup dekat) untuk membuat pembacaan range murah. Dengan primary key bigint, baris baru mendarat dalam urutan yang kira-kira meningkat, jadi indeks primary cenderung tetap kompak dan ramah locality. Dengan UUID acak, insert tersebar di indeks, yang bisa menciptakan lebih banyak page split dan urutan di disk yang lebih berantakan.

Read adalah tempat banyak tim pertama kali menyadari perbedaan. Kunci yang lebih besar berarti indeks lebih besar, dan indeks lebih besar berarti lebih sedikit halaman berguna yang muat di RAM. Itu menurunkan hit rate cache dan meningkatkan I/O, terutama pada layar yang banyak join seperti “daftar order dengan info customer”. Jika working set Anda tidak muat di memori, skema yang banyak memakai UUID bisa mendorong Anda melewati ambang itu lebih cepat.

Tulis juga bisa berubah. Insert UUID acak dapat menambah churn pada indeks, menambah tekanan pada autovacuum, dan muncul sebagai lonjakan latensi saat periode sibuk.

Jika Anda mengukur perbandingan UUID vs bigint di PostgreSQL, lakukan jujur: skema sama, indeks sama, fillfactor sama, dan cukup banyak baris untuk melebihi RAM (bukan 10k). Ukur p95 latency dan I/O, dan uji cache yang hangat maupun dingin.

Jika Anda membangun aplikasi di AppMaster pada PostgreSQL, ini sering muncul sebagai halaman daftar yang lebih lambat dan beban database yang lebih tinggi jauh sebelum terlihat sebagai “masalah CPU”.

Keamanan dan kegunaan pada sistem publik

Jika ID keluar dari database dan muncul di URL, response API, tiket dukungan, dan layar mobile, pilihan itu memengaruhi keamanan sekaligus kegunaan sehari-hari.

ID bigint mudah untuk manusia. Pendek, bisa dibaca lewat telepon, dan tim dukungan cepat melihat pola seperti “semua order gagal sekitar 9.200.000.” Itu mempercepat debugging, khususnya saat bekerja dari log atau screenshot pelanggan.

UUID membantu ketika Anda mengekspos identifier ke publik. UUID sulit ditebak, jadi scraping sederhana seperti mencoba /users/1, /users/2 tidak berhasil. Itu juga membuat pihak luar lebih sulit menebak berapa banyak record yang Anda miliki.

Perangkapnya adalah berpikir “sulit ditebak” berarti “aman.” Jika pengecekan otorisasi lemah, ID bigint yang dapat diprediksi bisa disalahgunakan dengan cepat, tetapi UUID tetap bisa dicuri dari tautan yang dibagikan, log yang bocor, atau response API yang di-cache. Keamanan harus datang dari pengecekan izin, bukan menyembunyikan ID.

Pendekatan praktis:

  • Terapkan pengecekan kepemilikan atau peran pada setiap operasi baca dan tulis.
  • Jika mengekspos ID di API publik, gunakan UUID atau token publik terpisah.
  • Jika butuh referensi ramah manusia, simpan bigint internal untuk operasi.
  • Jangan menyematkan makna sensitif di ID itu sendiri (mis. tipe user).

Contoh: portal pelanggan menampilkan ID faktur. Jika faktur pakai bigint dan API hanya memeriksa “invoice exists”, seseorang bisa iterasi nomor dan mengunduh faktur orang lain. Perbaiki pengecekan dulu. Lalu putuskan apakah UUID untuk ID faktur publik mengurangi risiko dan beban dukungan.

Di platform seperti AppMaster, di mana ID mengalir lewat API yang digenerate dan aplikasi mobile, default paling aman adalah otorisasi konsisten ditambah format ID yang klien bisa tangani dengan andal.

Bagaimana ID mengalir lewat API dan aplikasi mobile

Ubah skema jadi API produksi
Hasilkan backend Go dengan API bersih yang menjaga konsistensi penanganan ID.
Buat Backend

Tipe database yang Anda pilih tidak tetap di database. Itu bocor ke setiap batas: URL, payload JSON, penyimpanan klien, log, dan analytics.

Jika Anda mengubah tipe ID nanti, kerusakannya jarang “hanya migrasi.” Foreign key harus berubah di mana-mana, bukan hanya di tabel utama. ORM dan code generator mungkin menghasilkan ulang model, tapi integrasi masih mengharapkan format lama. Bahkan endpoint sederhana GET /users/123 menjadi rumit saat ID berubah menjadi UUID 36-karakter. Anda juga harus memperbarui cache, antrean pesan, dan tempat lain yang menyimpan ID sebagai integer.

Untuk API, pilihan terbesar adalah format dan validasi. Bigint dikirim sebagai angka, tapi beberapa sistem (dan bahasa) berisiko masalah presisi pada nilai sangat besar jika diparsing sebagai floating point. UUID dikirim sebagai string, yang lebih aman untuk parsing, tetapi Anda perlu validasi ketat agar tidak ada "UUID hampir benar" masuk ke log dan database.

Di mobile, ID terus diserialisasi dan disimpan: response JSON, tabel SQLite lokal, dan antrean offline yang menyimpan aksi sampai jaringan kembali. ID numerik lebih kecil, tapi string UUID sering lebih mudah diperlakukan sebagai token opak. Yang menyebabkan sakit nyata adalah inkonsistensi: satu lapisan menyimpan sebagai integer, lapisan lain sebagai text, dan perbandingan atau join menjadi rapuh.

Beberapa aturan yang menjaga tim dari masalah:

  • Pilih satu representasi kanonis untuk API (seringnya string) dan patuhi itu.
  • Validasi ID di edge dan kembalikan error 400 yang jelas.
  • Simpan representasi yang sama di cache lokal dan antrean offline.
  • Log ID menggunakan nama dan format field yang konsisten antar layanan.

Jika Anda membangun klien web dan mobile dengan stack yang digenerate (mis. AppMaster menghasilkan backend dan native apps), kontrak ID yang stabil lebih penting lagi karena menjadi bagian dari setiap model dan request yang digenerate.

Kesiapan sharding dan sistem terdistribusi

“Siap sharding” biasanya berarti Anda bisa membuat ID di lebih dari satu tempat tanpa merusak keunikan, dan bisa memindahkan data antar node nanti tanpa menulis ulang setiap foreign key.

UUID populer di setup multi-region atau multi-writer karena setiap node bisa menghasilkan ID unik tanpa meminta sequence pusat. Itu mengurangi koordinasi dan memudahkan menerima tulis di region berbeda dan menggabungkan data nanti.

Bigint masih bisa bekerja, tapi Anda perlu rencana. Opsi umum termasuk mengalokasikan rentang numerik per shard (shard 1 pakai 1–1B, shard 2 pakai 1B–2B), menjalankan sequence terpisah dengan prefix shard, atau menggunakan ID ala Snowflake (bit waktu plus bit mesin/shard). Ini bisa menjaga indeks lebih kecil dibanding UUID dan mempertahankan beberapa ordering, tapi menambah aturan operasional yang harus ditegakkan.

Pertukaran yang penting sehari-hari:

  • Koordinasi: UUID hampir tidak butuh; bigint sering butuh perencanaan rentang atau layanan generator.
  • Tabrakan: Kolisi UUID sangat tidak mungkin; bigint aman hanya jika aturan alokasi tidak pernah tumpang tindih.
  • Pengurutan: banyak skema bigint kira-kira berurutan waktu; UUID sering acak kecuali Anda pakai varian berurutan waktu.
  • Kompleksitas: bigint ter-shard tetap sederhana hanya jika tim disiplin.

Bagi banyak tim, “siap sharding” sebenarnya berarti “siap migrasi.” Jika Anda sekarang di satu database, pilih ID yang memudahkan pekerjaan saat ini. Jika Anda sudah membangun multi-writer (mis. lewat API yang digenerate dan mobile offline), putuskan lebih awal bagaimana ID dibuat dan divalidasi antar layanan.

Langkah demi langkah: memilih strategi ID yang tepat

Kirim tanpa terkunci dini
Deploy ke cloud atau ekspor kode sumber saat Anda siap self-host.
Deploy Sekarang

Mulailah dengan menamai bentuk nyata aplikasi Anda. Satu database PostgreSQL di satu region punya kebutuhan berbeda dari sistem multi-tenant, setup yang mungkin nanti dipisah per region, atau aplikasi mobile yang harus membuat record offline dan sinkronisasi nanti.

Selanjutnya, jujurlah tentang di mana ID akan muncul. Jika identifier tetap di backend (job, tools internal, panel admin), kesederhanaan sering menang. Jika ID muncul di URL, log yang dibagikan pelanggan, tiket dukungan, atau deep link mobile, prediktabilitas dan privasi lebih penting.

Gunakan ordering sebagai faktor penentu, bukan pertimbangan belakangan. Jika Anda bergantung pada feed “terbaru dulu”, pagination stabil, atau audit trail yang mudah discan, ID berurutan (atau ID berurutan waktu) mengurangi kejutan. Jika pengurutan tidak terkait primary key, Anda bisa memisahkan pilihan PK dan urut berdasarkan timestamp.

Alur keputusan praktis:

  1. Klasifikasikan arsitektur Anda (single DB, multi-tenant, multi-region, offline-first) dan apakah Anda mungkin menggabungkan data dari sumber banyak.
  2. Putuskan apakah ID adalah identifier publik atau murni internal.
  3. Konfirmasi kebutuhan ordering dan pagination. Jika butuh urutan insert alami, hindari ID yang sepenuhnya acak.
  4. Jika memilih UUID, pilih versi dengan sengaja: acak (v4) untuk ketidakbolehan ditebak, atau berurutan waktu untuk locality indeks lebih baik.
  5. Kunci konvensi sejak awal: satu bentuk teks kanonis, aturan huruf, validasi, dan bagaimana setiap API mengembalikan dan menerima ID.

Contoh: jika aplikasi mobile membuat "draft orders" saat offline, UUID memungkinkan perangkat membuat ID dengan aman sebelum server melihatnya. Di tools seperti AppMaster itu juga nyaman karena format ID sama mengalir dari database ke API ke web dan native apps tanpa perlakuan khusus.

Kesalahan umum dan jebakan yang harus dihindari

Buat paging yang dapat diprediksi
Uji pagination cursor dan aturan sorting menggunakan alur UI nyata Anda.
Hasilkan Web App

Sebagian besar debat ID salah karena orang memilih tipe ID untuk satu alasan, lalu terkejut oleh efek sampingnya nanti.

Salah satu kesalahan umum adalah memakai UUID acak sepenuhnya pada tabel tulis panas lalu heran kenapa insert terasa melonjak. Nilai acak menyebarkan baris baru di indeks, yang bisa berarti lebih banyak page split dan kerja lebih banyak untuk database saat beban tinggi. Jika tabel write-heavy, pikirkan locality insert sebelum memutuskan.

Masalah sering lain adalah mencampur tipe ID antar layanan dan klien. Misal satu layanan pakai bigint, layanan lain pakai UUID, dan API Anda berakhir dengan ID numerik dan string. Itu sering menjadi bug halus: parser JSON kehilangan presisi pada angka besar, kode mobile menganggap ID sebagai angka di satu layar dan string di layar lain, atau kunci cache tidak cocok.

Perangkap ketiga adalah menganggap “ID yang sulit ditebak” sebagai kontrol akses. Bahkan pakai UUID, Anda tetap perlu pengecekan otorisasi yang tepat.

Terakhir, tim mengubah tipe ID terlambat tanpa rencana. Bagian tersulit bukan primary key sendiri, melainkan semua yang melekat padanya: foreign key, tabel join, URL, event analytics, deep link mobile, dan state klien yang disimpan.

Untuk menghindari sakit:

  • Pilih satu tipe ID untuk API publik dan patuhi itu.
  • Perlakukan ID sebagai string di klien untuk menghindari kasus tepi numerik.
  • Jangan gunakan random ID sebagai kontrol akses.
  • Jika harus migrasi, versi API dan rencanakan untuk klien yang bertahan lama.

Jika Anda membangun dengan platform pembuat kode seperti AppMaster, konsistensi lebih penting karena tipe ID yang sama mengalir dari skema database ke backend yang digenerate dan ke web serta mobile apps.

Daftar periksa cepat sebelum memutuskan

Jika buntu, jangan mulai dari teori. Mulai dari bagaimana produk Anda akan terlihat dalam setahun, dan berapa banyak tempat ID itu akan mengalir.

Tanyakan:

  • Seberapa besar tabel terbesar dalam 12–24 bulan ke depan, dan apakah Anda akan menyimpan sejarah bertahun-tahun?
  • Apakah Anda perlu ID yang kira-kira terurut menurut waktu pembuatan untuk paging dan debugging mudah?
  • Apakah lebih dari satu sistem akan membuat record sekaligus, termasuk mobile offline atau job latar?
  • Apakah ID akan muncul di URL, tiket dukungan, ekspor, atau screenshot yang dibagikan pelanggan?
  • Bisakah setiap klien memperlakukan ID dengan cara yang sama (web, iOS, Android, skrip), termasuk validasi dan penyimpanan?

Setelah menjawab, periksa plumbing. Jika pakai bigint, pastikan rencana pembuatan ID di setiap environment (terutama dev lokal dan impor). Jika pakai UUID, pastikan kontrak API dan model klien menangani string ID secara konsisten, dan tim nyaman membaca serta membandingkannya.

Tes realitas cepat: jika aplikasi mobile perlu membuat order saat offline dan sinkronisasi nanti, UUID sering mengurangi kerja koordinasi. Jika aplikasi Anda kebanyakan online dan Anda ingin indeks yang ringkas, bigint biasanya lebih mudah.

Jika Anda membangun di AppMaster, putuskan lebih awal supaya model database, endpoint API, dan klien mobile tetap konsisten saat Anda menghasilkan ulang dan menumbuhkan proyek.

Contoh skenario realistis

Prototipe halaman daftar dan join
Validasi perilaku indeks dan pagination dengan data dan layar yang realistis.
Buat Prototipe

Sebuah perusahaan kecil punya tool operasi internal, portal pelanggan, dan aplikasi mobile untuk staf lapangan. Ketiganya mengakses database PostgreSQL yang sama lewat satu API. Record baru dibuat sepanjang hari: ticket, foto, update status, dan invoice.

Dengan bigint, payload API ringkas dan mudah dibaca:

{ "ticket_id": 4821931, "customer_id": 91244 }

Pagination terasa alami: ?after_id=4821931&limit=50. Mengurutkan berdasarkan id biasanya cocok dengan waktu pembuatan, jadi “ticket terbaru” cepat dan dapat diprediksi. Debugging juga sederhana: dukungan bisa minta “ticket 4821931” dan kebanyakan orang bisa mengetiknya tanpa salah.

Dengan UUID, payload lebih panjang:

{ "ticket_id": "3f9b3c0a-7b9c-4bf0-9f9b-2a1b3c5d1d2e" }

Jika pakai UUID v4 acak, insert mendarat di seluruh indeks. Itu bisa berarti lebih banyak churn indeks dan sedikit mengacaukan debugging sehari-hari (copy/paste jadi hal biasa). Pagination sering bergeser ke token cursor daripada "after id" sederhana.

Jika pakai UUID berurutan waktu, Anda mempertahankan sebagian besar perilaku “terbaru dulu” sambil tetap menghindari ID yang mudah ditebak di URL publik.

Dalam praktiknya, tim biasanya memperhatikan empat hal:

  • Seberapa sering ID diketik oleh manusia dibanding disalin
  • Apakah "sort by id" cocok dengan "sort by created"
  • Seberapa bersih dan stabil pagination cursor terasa
  • Seberapa mudah menelusuri satu record di log, panggilan API, dan layar mobile

Langkah selanjutnya: pilih default, uji, dan standarkan

Sebagian besar tim buntu karena menginginkan jawaban sempurna. Anda tidak butuh sempurna. Anda butuh default yang cocok untuk produk hari ini, plus cara cepat membuktikan itu tidak merugikan nanti.

Aturan yang bisa Anda standardkan:

  • Gunakan bigint ketika Anda ingin indeks terkecil, pengurutan yang dapat diprediksi, dan debugging mudah.
  • Gunakan UUID ketika ID harus sulit ditebak di URL, Anda mengharapkan pembuatan offline (mobile), atau Anda ingin lebih sedikit tabrakan antar sistem.
  • Jika mungkin membagi data per tenant atau region nanti, pilih rencana ID yang bekerja antar node (UUID, atau skema bigint terkoordinasi).
  • Pilih satu sebagai default dan buat pengecualian jarang. Konsistensi biasanya mengalahkan micro-optimasi pada satu tabel.

Sebelum mengunci keputusan, jalankan spike kecil. Buat tabel dengan ukuran baris realistis, insert 1–5 juta baris, dan bandingkan (1) ukuran indeks, (2) waktu insert, dan (3) beberapa query umum dengan primary key dan beberapa indeks sekunder. Lakukan di hardware nyata dan dengan bentuk data nyata.

Jika khawatir akan perubahan nanti, rencanakan migrasi agar membosankan:

  • Tambah kolom ID baru dan index unik.
  • Dual-write: isi kedua ID untuk baris baru.
  • Backfill baris lama secara bertahap.
  • Perbarui API dan klien untuk menerima ID baru (biarkan yang lama bekerja selama transisi).
  • Alihkan pembacaan, lalu drop kunci lama saat log dan metrik sudah bersih.

Jika Anda membangun di AppMaster (appmaster.io), sebaiknya putuskan sejak awal karena konvensi ID mengalir lewat model PostgreSQL Anda, API yang digenerate, dan web serta aplikasi mobile native. Tipe spesifik itu penting, tetapi konsistensi biasanya lebih penting begitu Anda punya pengguna nyata dan banyak klien.

FAQ

Haruskah saya menggunakan bigint atau UUID sebagai primary key di PostgreSQL?

Biasakan bigint ketika Anda punya satu database PostgreSQL, sebagian besar penulisan terjadi di server, dan Anda mengutamakan indeks yang ringkas serta perilaku insert yang dapat diprediksi. Pilih UUID saat ID harus dibuat di banyak tempat (beberapa service, mobile offline, sharding di masa depan) atau ketika Anda tidak ingin ID publik mudah ditebak.

Kenapa UUID membuat indeks dan penyimpanan membesar begitu banyak?

Karena ID disalin ke banyak tempat: indeks primary key, setiap indeks sekunder (sebagai penunjuk baris), kolom foreign key di tabel lain, dan tabel join. UUID berukuran 16 byte sedangkan bigint 8 byte, jadi perbedaan ukuran berlipat di seluruh skema Anda dan dapat menurunkan hit rate cache.

Apakah UUID akan memperlambat insert dibanding bigint?

Pada tabel dengan penulisan tinggi, ya. UUID acak (mis. v4) menyebarkan insert ke seluruh B-tree, meningkatkan page split dan churn indeks di bawah beban. Jika Anda ingin tetap pakai UUID tapi juga ingin penulisan yang lebih mulus, gunakan strategi UUID berurutan waktu agar kunci baru biasanya berada di ujung indeks.

Apakah saya akan merasakan pembacaan yang lebih lambat dengan UUID?

Biasanya terasa sebagai I/O lebih banyak, bukan CPU yang lebih lambat. Kunci yang lebih besar berarti indeks lebih besar, sehingga lebih sedikit halaman yang muat di memori; join dan lookup bisa menyebabkan lebih banyak pembacaan disk. Perbedaan paling terasa pada tabel besar, query yang berat join, dan ketika working set tidak muat di RAM.

Apakah UUID lebih aman daripada bigint di API publik?

UUID membantu mengurangi tebakan sederhana seperti /users/1, tapi mereka tidak menggantikan otorisasi. Jika pengecekan izin salah, UUID masih bisa bocor dan digunakan kembali. Anggap UUID sebagai kemudahan untuk ID publik, dan andalkan kontrol akses ketat untuk keamanan sejati.

Bagaimana cara terbaik merepresentasikan ID di JSON API?

Pilih satu representasi kanonis dan konsisten. Default praktisnya adalah memperlakukan ID sebagai string di API request dan response, meskipun database menggunakan bigint, karena ini menghindari masalah presisi di klien dan membuat validasi lebih sederhana. Apa pun pilihan Anda, pertahankan konsistensi di web, mobile, log, dan cache.

Apakah bigint menyebabkan masalah di JavaScript atau aplikasi mobile?

Bigint bisa bermasalah di beberapa klien jika diparsing sebagai floating-point karena kehilangan presisi pada nilai besar. UUID menghindari itu karena berupa string, tapi mereka lebih panjang dan mudah salah tangani jika Anda tidak melakukan validasi ketat. Pendekatan teraman adalah konsistensi: satu tipe di mana saja, dengan validasi jelas di edge API.

Apa yang harus saya pilih jika mungkin nanti saya melakukan sharding atau multi-region?

UUID adalah pilihan sederhana karena bisa dibuat independen tanpa koordinasi sequence pusat. Bigint masih bisa dipakai, tetapi Anda perlu aturan seperti rentang per-shard atau generator ala Snowflake yang harus ditegakkan terus-menerus. Jika menginginkan cerita terdistribusi paling mudah, pilih UUID (lebih baik yang berurutan waktu).

Seberapa menyakitkan migrasi dari bigint ke UUID (atau sebaliknya)?

Mengganti tipe primary key menyentuh lebih dari satu kolom. Anda harus memperbarui foreign key, tabel join, kontrak API, penyimpanan klien, cache, event analytics, dan integrasi yang menyimpan ID sebagai angka atau string. Jika mungkin perlu berubah, rencanakan migrasi bertahap dengan dual-write dan jangka transisi yang panjang.

Bisakah saya memakai keduanya: bigint secara internal dan UUID secara eksternal?

Memiliki kunci bigint internal untuk efisiensi database, dan tambahkan UUID publik (atau token) terpisah untuk URL dan API eksternal. Ini memberi indeks yang ringkas dan debugging internal yang mudah sambil menghindari enumerasi sederhana pada ID publik. Kuncinya adalah menentukan sejak awal mana yang menjadi “public ID” dan jangan mencampurnya sembarangan.

Mudah untuk memulai
Ciptakan sesuatu yang menakjubkan

Eksperimen dengan AppMaster dengan paket gratis.
Saat Anda siap, Anda dapat memilih langganan yang tepat.

Memulai