17 Eyl 2025·7 dk okuma

PostgreSQL'de UUID vs bigint: Ölçeklenebilir kimlik seçimi

PostgreSQL'de UUID ile bigint'i karşılaştırın: indeks boyutu, sıralama, shard hazırlığı ve ID'lerin API, web ve mobil uygulamalarda nasıl aktığını öğrenin.

PostgreSQL'de UUID vs bigint: Ölçeklenebilir kimlik seçimi

ID seçimi göründüğünden daha önemli

Her PostgreSQL satırı tekrar bulunabilmek için kararlı bir yola ihtiyaç duyar. ID bunu yapar: kaydı benzersiz şekilde tanımlar, genelde birincil anahtardır ve ilişkiler için tutkal olur. Diğer tablolar onu yabancı anahtar olarak saklar, sorgular üzerinde join yapılır ve uygulamalar “o müşteri”, “o fatura” veya “o destek bileti” için onu taşır.

ID'ler her yere sızdığından seçim sadece bir veritabanı detayı değildir. Sonradan indeks boyutu, yazma kalıpları, sorgu hızı, önbellek isabet oranları ve ürün işleri (analitik, importlar, hata ayıklama) üzerinde etkisi olur. Ayrıca URL'lerde ve API'lerde neyi açıkladığınızı ve bir mobil uygulamanın veriyi güvenle depolayıp senkronize etmesinin ne kadar kolay olduğunu etkiler.

Çoğu ekip nihayetinde PostgreSQL'de UUID ile bigint'i karşılaştırır. Basitçe söylemek gerekirse, seçiminiz iki şey arasındadır:

  • bigint: 64-bitlik sayı, genellikle bir sequence ile üretilir (1, 2, 3...).
  • UUID: 128-bitlik tanımlayıcı, genelde rastgele görünümlü veya zaman-sıralı şekilde üretilir.

Hiçbir seçenek her durumda kazanan değildir. Bigint genelde indeksler ve sıralama için kompakt ve dosttur. UUID'ler ise sistemler arası küresel benzersizlik gerektiğinde, halka açık ID'lerin daha güvenli olması istendiğinde veya verinin birçok yerde (çoklu servisler, çevrimdışı mobil veya ileride shard) yaratılması bekleniyorsa uygundur.

Kullanışlı bir kural: sadece bugün nasıl saklanacağına göre değil, verinizin nasıl oluşturulup paylaşılacağına göre karar verin.

Bigint ve UUID temelleri, basitçe

İnsanlar PostgreSQL'de UUID vs bigint karşılaştırırken satırları isimlendirmenin iki yolu arasında seçim yaparlar: küçük, sayaç benzeri bir sayı mı yoksa daha uzun, küresel olarak benzersiz bir değer mi.

Bir bigint ID 64-bitlik bir tam sayıdır. PostgreSQL'de genellikle bir identity column (veya eski serial deseni) ile üretilir. Veritabanı arka planda bir sequence tutar ve her insert'te bir sonraki sayıyı verir. Bu, ID'lerin genelde 1, 2, 3, 4... şeklinde olacağı anlamına gelir. Basittir, okunması kolaydır ve araçlarda, raporlarda kullanışlıdır.

Bir UUID (Universally Unique Identifier) 128 bittir. Genelde tirelerle birlikte 36 karakter olarak yazılır, örneğin 550e8400-e29b-41d4-a716-446655440000. Yaygın türler şunlardır:

  • v4: rastgele UUID'ler. Her yerde kolayca üretilebilir ama oluşturulma sırasına göre sıralanmazlar.
  • v7: zaman-sıralı UUID'ler. Hâlâ benzersizdirler, ancak zamanla kabaca artacak şekilde tasarlanmışlardır.

Depolama ilk pratik farklardan biridir: bigint 8 bayt, UUID 16 bayt kullanır. Bu boyut farkı indekslerde görünür ve önbellek isabet oranlarını etkileyebilir (veritabanı aynı belleğe daha az indeks girdisi sığdırabilir).

Ayrıca ID'lerin veritabanı dışındaki yerlerini düşünün. Bigint ID'ler URL'lerde kısadır ve loglarda veya destek biletlerinde okunması kolaydır. UUID'ler daha uzundur ve yazması can sıkıcıdır, ama tahmin edilmesi zordur ve gerektiğinde istemcilerde güvenle üretilebilirler.

İndeks boyutu ve tablo şişmesi: ne değişir

Bigint ile UUID arasındaki en büyük pratik fark boyuttur. Bigint 8 bayttır; UUID 16 bayttır. Bu küçük fark, indekslerin ID'leri birçok yerde tekrar ettiğini unutana kadar önemsiz görünür.

Birincil anahtar indeksiniz çabuk erişilebilir (hot) kalmak zorundadır. Daha küçük bir indeks, shared buffers ve CPU cache'ine daha fazla sığar; böylece lookup ve join'ler daha az disk okuması gerektirir. UUID birincil anahtarlarında aynı satır sayısı için indeks genellikle önemli ölçüde daha büyüktür.

Çarpan etkisi ikincil indekslerdedir. PostgreSQL B-tree indekslerinde her ikincil indeks girdisi ayrıca birincil anahtar değerini de saklar (veritabanının satırı bulabilmesi için). Bu yüzden genişleyen ID'ler sadece birincil indeksinizi değil, eklediğiniz her diğer indeksi de şişirir. Üç ikincil indeksiniz varsa, UUID'lerin ekstra 8 baytı aslında dört yerde görünür.

Yabancı anahtarlar ve join tabloları da bunu hisseder. ID'nizi referans eden her tablo bu değeri kendi satırlarında ve indekslerinde saklar. Çoktan-çoğa join tablosu çoğunlukla iki yabancı anahtar artı biraz overhead olduğundan, anahtar genişliğini iki katına çıkarmak boyut üzerinde büyük fark yaratabilir.

Pratikte:

  • UUID'ler genelde birincil ve ikincil indeksleri büyütür ve fark ek indekslerle beraber katlanır.
  • Daha büyük indeksler daha fazla bellek baskısı ve yük altında daha fazla page okuması demektir.
  • ID'yi referans eden tablo sayısı arttıkça boyut farkı daha önemli hale gelir.

Eğer bir kullanıcı ID'si users, orders, order_items ve audit_log içinde görünüyorsa, aynı değer tüm bu tablolarda saklanıp indekslenir. Daha geniş bir ID seçmek bir ID kararı kadar bir depolama kararıdır.

Sıralama düzeni ve yazma kalıpları: ardışık vs rastgele ID'ler

Çoğu PostgreSQL birincil anahtarı B-tree indeks üzerinde oturur. B-tree, yeni satırlar indeksin sonuna yakın düştüğünde en iyi çalışır; çünkü veritabanı eklemeleri ekleyerek minimal yeniden düzenleme ile yapabilir.

Ardışık ID'ler: depolama dostu ve öngörülebilir

Bir bigint identity veya sequence ile yeni ID'ler zamanla artar. Insert'lar genelde indeksin en sağ kısmına düşer, böylece sayfalar dolu kalır, cache sıcak kalır ve PostgreSQL daha az ekstra iş yapar.

Bu, ORDER BY id çalıştırmasanız bile önemlidir. Yazma yolu yine de her yeni anahtarı sıralı sıraya koymak zorundadır.

Rastgele UUID'ler: daha fazla dağılım, daha fazla çalkantı

Rastgele bir UUID (v4 yaygındır) insert'ları indeks boyunca dağıtır. Bu, PostgreSQL'in yeni indeks sayfaları tahsis etme ve yer açmak için girdileri taşıma ihtimalini artırır; buna page split denir. Sonuç daha fazla yazma amplifikasyonu: daha fazla indeks baytı yazılır, daha fazla WAL üretilir ve genelde daha fazla arka plan işi (vacuum ve bloat yönetimi) gerekir.

Zaman-sıralı UUID'ler hikâyeyi değiştirir. Zamanla kabaca artan UUID'ler (UUIDv7 tarzı veya diğer zaman tabanlı şemalar) locality'nin çoğunu geri getirir, hala 16 bayt olurlar ve API'nizde UUID gibi görünürler.

Bu farkları en çok yüksek insert oranlarına, belleğe sığmayan büyük tablolara ve birden çok ikincil indekse sahip olduğunuzda hissedersiniz. Eğer page split'lerden kaynaklanan yazma gecikmesi spike'larına duyarlıysanız, sıcak yazma tablolarında tamamen rastgele ID'lerden kaçının.

Örnek: gün boyu mobil uygulama logları alan yoğun bir events tablosu, tamamen rastgele UUID'lerdense ardışık anahtarlar veya zaman-sıralı UUID'lerle genelde daha düzgün çalışır.

Gerçekçi şekilde hissedilen performans etkisi

Erken kilitlenmeden gönderin
Hazır olduğunuzda buluta deploy edin veya kaynak kodu dışa aktarın ve self-host edin.
Hemen Dağıt

Gerçek dünyadaki yavaşlamalar genelde “UUID yavaştır” veya “bigint hızlıdır” gibi basit genellemeler değil. Asıl olan veritabanının sorgunuza cevap vermek için ne kadarına dokunmak zorunda kaldığıdır.

Sorgu planları esasen bir filtre için indeks taraması yapıp yapamayacaklarına, anahtar üzerinde hızlı join yapılıp yapılamayacağına ve tablonun fiziksel olarak sıralı (ya da yeterince yakın) olup olmadığına bakar. Bigint PK ile yeni satırlar kabaca artan sırada geldiği için birincil anahtar indeksi kompakt ve locality-dostu kalma eğilimindedir. Rastgele UUID'lerde insert'lar indekste dağılır, bu da daha fazla page split ve disk üzerindeki daha dağınık bir düzen yaratır.

Okumalar birçok ekibin ilk fark ettiği noktadır. Daha büyük anahtarlar daha büyük indeksler demektir ve daha büyük indeksler RAM'e daha az sığar; bu da önbellek isabet oranlarını azaltır ve IO'yu artırır, özellikle müşteri bilgisiyle join yapan “siparişleri listele” gibi ekranlarda. Çalışma setiniz belleğe sığmıyorsa, UUID-ağırlıklı şemalar sizi bu eşiği daha erken geçirebilir.

Yazmalar da değişebilir. Rastgele UUID insert'leri indekste daha fazla çalkantı yaratarak autovacuum üzerinde baskı oluşturabilir ve yoğun dönemlerde gecikme spike'ları olarak ortaya çıkabilir.

UUID vs bigint'i ölçerken dürüst olun: aynı şema, aynı indeksler, aynı fillfactor ve RAM'i aşan yeterli satır sayısı ile (10k değil) test edin. p95 gecikmeyi ve IO'yu ölçün; hem sıcak hem soğuk cache senaryolarını deneyin.

Eğer AppMaster üzerinde PostgreSQL ile uygulamalar inşa ediyorsanız, bu genelde liste sayfalarının daha yavaş olması ve veritabanı yükünün kullanıcı tarafından fark edilmeden önce artması şeklinde ortaya çıkar.

Halka açık sistemlerde güvenlik ve kullanılabilirlik

ID'ler veritabanını terk edip URL'lerde, API cevaplarında, destek biletlerinde ve mobil ekranlarda görünüyorsa seçim hem güvenlik hem günlük kullanım açısından etki eder.

Bigint ID'ler insanlar için kolaydır. Kısadırlar, telefonda okunabilirler ve destek ekibiniz “tüm başarısız siparişler yaklaşık 9,200,000 civarında” gibi desenleri hızlıca görebilir. Bu, loglardan veya müşteri ekran görüntülerinden çalışırken hata ayıklamayı hızlandırır.

UUID'ler halka açık identifier'lar için faydalıdır. UUID tahmin edilmesi zordur; /users/1, /users/2, /users/3 gibi basit scraping işe yaramaz. Dışarıdakilerin kaç kayıt olduğunu çıkarmasını da zorlaştırır.

Ama “tahmin edilemez” demek “güvenli” demek değildir. Yetkilendirme kontrolleri zayıfsa, öngörülebilir bigint ID'ler kötüye kullanılabilir; fakat UUID'ler de paylaşılan bir bağlantıdan, sızmış bir logtan veya önbelleğe alınmış bir API cevabından çalınabilir. Güvenlik kimlik gizlemeyle değil, izin kontrolleriyle sağlanır.

Pratik yaklaşım:

  • Her okuma ve yazmada sahiplik veya rol kontrollerini uygulayın.
  • Eğer ID'leri halka açık API'lerde gösteriyorsanız, UUID'ler veya ayrı public token'lar kullanın.
  • İnsan-dostu referanslar istiyorsanız, ops için dahili bir bigint tutun.
  • ID'nin içinde (ör. kullanıcı türü gibi) hassas anlamlar kodlamayın.

Örnek: müşteri portalı fatura ID'lerini gösteriyor. Eğer faturalar bigint kullanıyorsa ve API sadece “fatura var mı” diye kontrol ediyorsa, biri sayıları iterate edip başkalarının faturalarını indirebilir. Önce kontrolleri düzeltin. Sonra halka açık fatura ID'lerini UUID'ye çevirmenin riski ve destek yükünü azaltıp azaltmayacağını değerlendirin.

AppMaster gibi ID'lerin oluşturulan API'ler ve mobil uygulamalar arasında aktığı platformlarda, en güvenli varsayılan tutarlı yetkilendirme artı istemcilerin güvenle işleyebileceği bir ID formatıdır.

ID'lerin API'ler ve mobil uygulamalar üzerinden akışı

ID'ler evrildikçe esnek kalın
Gereksinimler değişse bile teknik borç oluşturmadan temiz kodu yeniden üretin.
Uygulamayı Yeniden Üret

Seçtiğiniz veritabanı türü veritabanında kalmaz. URL'lere, JSON payload'lara, istemci depolamalarına, log'lara ve analitiğe sızar.

ID tipini sonradan değiştirmek nadiren “sadece bir migration” olur. Yabancı anahtarlar her yerde değişmeli, sadece ana tabloda değil. ORM'ler ve kod üreteçleri modelleri yeniden oluşturabilir ama entegrasyonlar eski formatı beklemeye devam eder. Basit bir GET /users/123 endpoint'i bile ID 36 karakterlik bir UUID'ye dönüştüğünde karmaşıklaşır. Cache'leri, mesaj kuyruğu kayıtlarını ve ID'lerin tam sayı olarak saklandığı yerleri güncellemeniz gerekir.

API'ler için en büyük tercih format ve doğrulamadır. Bigint sayılar olarak gider, ama bazı sistemler (ve diller) onları kayan nokta olarak ayrıştırıp hassasiyet kaybına yol açabilir. UUID'ler string olarak gider; ayrıştırma açısından daha güvenlidir, ama kenarda sıkı doğrulama olmadan “neredeyse UUID” çöpleri loglara ve verilere karışabilir.

Mobilde, ID'ler sürekli serileştirilir ve saklanır: JSON yanıtları, local SQLite tabloları ve ağ gelene kadar eylemleri saklayan offline kuyruklar. Sayısal ID'ler daha küçüktür, ama string UUID'ler genelde opak token olarak işlenmesi daha kolaydır. Gerçek acı veren durum tutarsızlıktır: bir katman ID'yi integer, başka bir katman text olarak saklarsa karşılaştırmalar veya join'ler kırılgan hale gelir.

Takımı sorunlardan uzak tutacak birkaç kural:

  • API için bir kanonik temsil seçin (çoğunlukla string) ve buna sadık kalın.
  • Kenarda ID'leri doğrulayın ve net 400 hataları döndürün.
  • Yerel cache ve offline kuyruklarda aynı temsili saklayın.
  • Hizmetler arası loglarda ve alan adlarında ID'leri tutarlı formatta kaydedin.

Eğer web ve mobil istemcileri jenerik bir yığınla (ör. AppMaster tarafından üretilen backend ve native uygulamalar) inşa ediyorsanız, stabil bir ID sözleşmesi daha da önemlidir çünkü bu her üretilen modelin ve isteğin bir parçası haline gelir.

Sharding hazırlığı ve dağıtık sistemler

“Sharding-ready” çoğunlukla ID'leri birden fazla yerde oluşturabilmeniz ve benzersizliğin bozulmaması anlamına gelir; ayrıca verileri daha sonra düğümler arasında yeniden yazmadan taşıyabilmeyi sağlar.

UUID'ler çoklu bölge veya çok-yazarlı kurulumlarda popülerdir çünkü herhangi bir düğüm merkezi bir sequence yerine benzersiz ID oluşturabilir. Bu koordinasyonu azaltır ve farklı bölgelerde yazmayı kabul etmeyi ve verileri sonra birleştirmeyi kolaylaştırır.

Bigint hâlâ çalışabilir, ama bir plan gerekir. Yaygın seçenekler: shard başına sayısal aralıklar atamak (shard 1: 1–1B, shard 2: 1B–2B), shard öneki ile ayrı sequence'ler çalıştırmak veya makine/shard bitleri ekleyen Snowflake benzeri ID'ler kullanmak. Bunlar UUID'lerden daha küçük indeksler ve biraz sıralama sağlayabilir, ama operasyonel kurallar gerektirir.

Günlük hayatı etkileyen takaslar:

  • Koordinasyon: UUID neredeyse hiç gerektirmez; bigint genelde aralık planlaması veya jeneratör servisi ister.
  • Çakışma: UUID çakışması son derece düşükken; bigint yalnızca tahsis kuralları asla çakışmayacak şekilde güvenlidir.
  • Sıralama: birçok bigint şeması kabaca zaman-sıralıdır; UUID genelde rastgeledir, zaman-sıralı varyantlar hariç.
  • Karmaşıklık: shard edilmiş bigint sadece ekip disiplinli olduğu sürece basit kalır.

Birçok ekip için “sharding-ready” gerçekte “geçişe hazır” demektir. Bugün tek bir veritabanındaysanız, ID'yi mevcut işi kolaylaştıracak şekilde seçin. Eğer zaten birden fazla yazıcı (ör. AppMaster ile üretilen API'ler ve mobil uygulamalar üzerinden) inşa ediyorsanız, ID'lerin hizmetler arasında nasıl oluşturulup doğrulanacağına erken karar verin.

Adım adım: doğru ID stratejisini seçmek

Şemayı üretime API'ye dönüştürün
ID işlemini tutarlı tutan temiz API'lerle Go backend'ler üretin.
Backend Oluştur

Önce uygulamanızın gerçek şeklini isimlendirin. Tek bir PostgreSQL veritabanı ve tek bölge mi, yoksa multi-tenant, ileride bölgelere bölünebilecek veya çevrimdışı çalışan mobil uygulamaların kayıt oluşturup sonra eşleştirdiği bir yapı mı?

Sonra dürüst olun: ID'ler nerelerde görünecek? Eğer tanımlayıcılar sadece backend içinde kalacaksa (işler, dahili araçlar, admin panelleri), sadelik genelde kazanır. ID'ler URL'lerde, müşterilerle paylaşılan loglarda, destek biletlerinde veya mobil deep link'lerde görünüyorsa, öngörülebilirlik ve gizlilik daha önem kazanır.

Sıralamayı karar verirken birincil anahtar seçimi bir kenara bırakmayın. Eğer “yeniler önce” feed'lerine, stabil sayfalamaya veya kolay taranabilen denetim kayıtlarına güveniyorsanız, ardışık ID'ler (veya zaman-sıralı ID'ler) sürprizleri azaltır. Eğer sıralama birincil anahtara bağlı değilse, PK seçimini ayrı tutup sıralama için bir timestamp kullanabilirsiniz.

Pratik karar akışı:

  1. Mimarinizi sınıflandırın (tek DB, multi-tenant, multi-bölge, offline-first) ve veriyi birleştirip birleştirmeyeceğinizi belirleyin.
  2. ID'lerin halka açık mı yoksa tamamen dahili mi olacağına karar verin.
  3. Sıralama ve sayfalama ihtiyaçlarınızı onaylayın. Doğal ekleme sırasına ihtiyacınız varsa, tamamen rastgele ID'lerden kaçının.
  4. UUID tercih ederseniz, bir versiyon seçin: tahmin edilemezlik için v4, daha iyi indeks locality için zaman-sıralı bir versiyon.
  5. Erken kuralları kilitleyin: tek kanonik metin formu, büyük/küçük harf kuralları, doğrulama ve API'lerin ID'leri nasıl döndüreceği ve kabul edeceği.

Örnek: bir mobil uygulama offline iken “taslak sipariş”ler oluşturuyorsa, UUID cihazın sunucuyu görmeden önce güvenle ID üretmesini sağlar. AppMaster gibi araçlarda bu aynı ID formatının veritabanından API'ye, web ve native uygulamalara özel durum olmadan akmasını da kolaylaştırır.

Yaygın hatalar ve tuzaklar

Çevrimdışı dostu ID'ler planlayın
Offline kuyruklar, senkron akışları ve native istemciler boyunca ID'leri kararlı tutun.
Mobil Uygulama Oluştur

Çoğu ID tartışması yanlış sebeple karar verildiği için ters sonuç verir. Bir tablo için bir ID tipi seçip sonradan yan etkilerinden şaşırmak yaygındır.

Yaygın bir hata, sıcak yazma tablosunda tamamen rastgele UUID kullanıp neden insert'lerin spike yaptığını merak etmektir. Rastgele değerler yeni satırları indeks üzerinde dağıtır; bu da page split'leri ve veritabanının yoğun iş yükünü artırır. Eğer tablo yazma ağırlıklıysa, insert locality'sini düşünün.

Diğer bir sorun, hizmetler ve istemciler arasında ID tiplerini karıştırmaktır. Örneğin bir servis bigint, diğeri UUID kullanıyorsa API'niz hem sayısal hem string ID'lerle dolabilir. Bu ince hatalara yol açar: JSON ayrıştırıcıların büyük sayılarda hassasiyeti kaybetmesi, mobil kodunun bir ekranda ID'yi sayı diğerinde string olarak ele alması veya cache anahtarlarının uyuşmaması.

Üçüncü tuzak, “tahmin edilemez ID = güvenlik” gibi düşünmektir. UUID kullansanız bile doğru yetkilendirme yapmazsanız sorun devam eder.

Son olarak, ekipler ID tipini geç değiştirmek istemezler ama yaparlar; en zor olan kısmı birincil anahtar değil, ona eklenmiş her şeydir: yabancı anahtarlar, join tabloları, URL'ler, analytics olayları, mobil deep link'ler ve istemcide saklanan durum.

Acıdan kaçınmak için:

  • Halka açık API'ler için bir ID tipi seçin ve ona bağlı kalın.
  • İstemcilerde ID'leri opak string olarak ele alın ki sayısal köşe durumları ortadan kalksın.
  • ID rastgeleliğini erişim kontrolü olarak kullanmayın.
  • Zorunlu bir geçiş yapacaksanız, API'yi versiyonlayın ve uzun ömürlü istemciler için plan yapın.

AppMaster gibi kod üreten platformlarla çalışıyorsanız, tutarlılık daha da önem kazanır çünkü aynı ID tipi veritabanı şemasından oluşturulan backend'e ve web/mobil uygulamalara akar.

Karar vermeden önce hızlı bir kontrol listesi

Sıkıştıysanız teoriden başlamak yerine ürününüzün bir yıl sonra nasıl görüneceği ve ID'nin kaç yerde dolaşacağıyla başlayın.

Sorular:

  • En büyük tablolar 12–24 ay içinde ne kadar büyür ve yıllık tarihçeyi saklamaya devam edecek misiniz?
  • Oluşturma zamanına göre kabaca sıralanan ID'lere ihtiyacınız var mı (kolay sayfalama ve hata ayıklama için)?
  • Aynı anda birden fazla sistem kayıt oluşturacak mı, çevrimdışı mobil uygulamalar veya background job'lar dahil?
  • ID URL'lerde, destek biletlerinde, dışa aktarma dosyalarında veya müşterilerle paylaşılan ekran görüntülerinde görünecek mi?
  • Her istemci ID'yi aynı şekilde ele alabilir mi (web, iOS, Android, script'ler), doğrulama ve depolama dahil?

Bunları cevapladıktan sonra altyapıyı kontrol edin. Eğer bigint kullanıyorsanız, her ortam için (özellikle lokal geliştirme ve importlar) ID üretimi planınız olsun. UUID kullanıyorsanız API sözleşmelerinizin ve istemci modellerinizin string ID'leri tutarlı şekilde ele aldığından ve ekibinizin onları okumaya alışkın olduğundan emin olun.

Hızlı gerçeklik testi: mobil uygulama offline iken bir sipariş oluşturup sonra senkronize edecekse, UUID genelde koordinasyon yükünü azaltır. Uygulamanız çoğunlukla online ise ve küçük indeksler istiyorsanız, bigint genelde daha kolaydır.

AppMaster üzerinde inşa ediyorsanız, erken karar verin; çünkü ID sözleşmesi PostgreSQL modelinizden oluşturulan API'lere ve hem web hem native mobil uygulamalara kadar akar.

Gerçekçi bir örnek senaryo

Uygun erişim kontrolleri ekleyin
Unguessable ID'lere bel bağlamadan doğrulama ve yetkilendirme mantığını uygulayın.
BP Editörünü Kullanın

Küçük bir şirketin iç operasyon aracı, müşteri portalı ve saha personeli için bir mobil uygulaması var. Üçü aynı PostgreSQL veritabanına tek bir API üzerinden erişiyor. Yeni kayıtlar gün boyunca oluşturuluyor: ticket'lar, fotoğraflar, durum güncellemeleri ve faturalar.

bigint ID'lerle API yükleri kompakt ve okunması kolaydır:

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

Sayfalama doğal hisseder: ?after_id=4821931&limit=50. id ile sıralama genelde oluşturma zamanına uyar, bu yüzden “en yeni ticket'lar” hızlı ve öngörülebilirdir. Hata ayıklama da kolaydır: destek “ticket 4821931” diye sorabilir ve çoğu kişi bunu yanlış yazmadan girebilir.

UUID ile payload'lar uzar:

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

Eğer rastgele UUID v4 kullanıyorsanız, insert'lar indekste her yere düşer. Bu daha fazla indeks çalkantısı ve biraz daha karmaşık günlük hata ayıklama (kopyala/yapıştır normal olur) anlamına gelebilir. Sayfalama genelde “after id” yerine cursor-stil token'lara kayar.

Zaman-sıralı UUID'ler kullanırsanız, çoğu “yeniler önce” davranışını korursunuz ve yine de halka açık URL'lerde tahmin edilebilirliği engellersiniz.

Pratikte ekipler genelde dört şeyi fark eder:

  • ID'lerin ne sıklıkla insanlar tarafından yazıldığı veya kopyalandığı
  • id ile sıralamanın created ile ne kadar uyuştuğu
  • Cursor sayfalamanın ne kadar temiz ve stabil hissettirdiği
  • Bir kaydı log'lar, API çağrıları ve mobil ekranlar arasında izleme kolaylığı

Sonraki adımlar: bir varsayılan seçin, test edin ve standartlaştırın

Çoğu ekip mükemmel bir cevap beklediği için takılır. Mükemmel olmanıza gerek yok; bugün ürününüze uyan bir varsayılan ve ileride zarar vermeyeceğini çabuk test edecek bir yol yeterlidir.

Standartlaştırılabilecek kurallar:

  • Küçük indeksler, öngörülebilir sıralama ve kolay hata ayıklama istiyorsanız bigint kullanın.
  • ID'lerin URL'lerde kolay tahmin edilememesini, çevrimdışı oluşturmayı veya sistemler arası çakışmasının minimizasyonunu istiyorsanız UUID kullanın.
  • Tenant veya bölgeye göre ileride veriyi ayırmayı düşünüyorsanız, düğümler arasında çalışan bir ID planı tercih edin (UUID veya koordine edilmiş bigint şeması).
  • Birini varsayılan yapın ve istisnaları nadir tutun. Tutarlılık genelde bir tabloyu mikro-optimize etmekten daha değerlidir.

Kilitlemeden önce küçük bir spike çalıştırın. Gerçekçi satır boyutuna sahip bir tablo oluşturun, 1 ila 5 milyon satır ekleyin ve karşılaştırın: (1) indeks boyutu, (2) insert süresi, (3) birkaç ortak sorgu ile birincil anahtar ve birkaç ikincil indeks. Gerçek donanımınızda ve veri şeklinizde yapın.

Değişiklik yapma korkunuz varsa, migrasyonu sıkıcı hale getirecek bir plan yapın:

  • Yeni ID sütunu ve benzersiz indeks ekleyin.
  • Çift-yazma: yeni satırlar için her iki ID'yi doldurun.
  • Eski satırları partiler halinde geri doldurun.
  • API'leri ve istemcileri yeni ID'yi kabul edecek şekilde güncelleyin (geçiş süresince eski ID çalışır halde kalsın).
  • Okumaları kesin, sonra log'lar ve metrikler temiz görünce eski anahtarı kaldırın.

AppMaster (appmaster.io) üzerinde inşa ediyorsanız, erken karar vermek faydalıdır çünkü ID konvansiyonu PostgreSQL modelinizden üretilen API'lere ve hem web hem native mobil uygulamalara akar. Türün önemi büyük olsa da, tutarlılık gerçek kullanıcılar ve birden fazla istemci olduğunda genelde daha önemlidir.

SSS

PostgreSQL'de birincil anahtar olarak bigint mi yoksa UUID mi kullanmalıyım?

Tek bir PostgreSQL veritabanınız varsa, çoğu yazma işlemi sunucuda gerçekleşiyorsa ve kompakt indeksler ile öngörülebilir ekleme davranışı önemsiyorsanız varsayılan olarak bigint kullanın. Birden çok yerde ID üretilmesi gerekiyorsa (birden çok servis, çevrimdışı mobil ya da gelecekte sharding) veya açık API'lerde kolay tahmin edilebilir ID'lerden kaçınmak istiyorsanız UUID seçin.

UUID'ler neden indeksleri ve depolamayı bu kadar büyütür?

ID değeri birçok yerde kopyalanır: birincil anahtar indeksi, her ikincil indeks (satırı bulmak için anahtar değeri saklanır), diğer tablolardaki yabancı anahtar sütunları ve join tabloları. UUID 16 bayt, bigint ise 8 bayt olduğu için bu boyut farkı şemada katlanarak büyür ve önbellek isabet oranlarını düşürebilir.

UUID'ler, bigint'e kıyasla eklemeleri yavaşlatır mı?

Sıcak yazma tablolarında evet. Tamamen rastgele UUID'ler (ör. v4) B-tree üzerinde eklemeleri her yere yayar; bu da page split'leri ve indeks çalkantısını artırır. UUID kullanmak istiyor ancak yazıların daha düz akmasını istiyorsanız, yeni anahtarların çoğunlukla sonda yer alacağı zaman sıralı bir UUID stratejisi kullanın.

UUID'lerle okumalarda yavaşlama hisseder miyim?

Çoğunlukla daha fazla IO olarak hissedilir, CPU yavaşlaması şeklinde değil. Daha büyük anahtarlar daha büyük indeksler demektir; daha büyük indeksler ise belleğe daha az sığar, bu da join ve lookup'larda daha fazla okuma gerektirir. Etki en çok büyük tablolar, join-ağırlıklı sorgular ve çalışma setiniz RAM'e sığmadığında görünür.

UUID'ler kamu API'lerinde bigint'ten daha güvenli midir?

UUID'ler /users/1 gibi kolay tahminleri zorlaştırır, ancak yetkilendirme kontrollerinin yerini almazlar. Yetki kontrolleri zayıfsa UUID'ler bile paylaşılan bir bağlantı, sızan bir log veya önbelleğe alınmış bir API cevabından kolayca ele geçirilebilir. UUID'leri halka açık tanımlayıcılar için bir kolaylık olarak görün; gerçek güvenlik için sıkı erişim kontrollerine güvenin.

JSON API'lerde ID'leri en iyi nasıl temsil etmeliyim?

Tek bir kanonik temsil seçin ve ona sadık kalın. Pratik bir varsayılan, API istek ve cevaplarında ID'leri string olarak ele almaktır; bu, istemci tarafı sayısal köşe durumlarını önler ve doğrulamayı basitleştirir. Ne seçerseniz seçin, web, mobil, log'lar ve cache'lerde tutarlı olsun.

JavaScript veya mobil uygulamalarda bigint sorun yaratır mı?

Büyük sayılar bazı istemcilerde (özellikle JavaScript) kayan nokta olarak ayrıştırıldığında hassasiyet kaybına yol açabilir. UUID'ler bu sorunu önler çünkü string'tirler, fakat uzun oldukları için yanlış kullanım veya yetersiz doğrulama sorunlarına yol açabilir. En güvenli yaklaşım: tutarlılık—her yerde tek bir tip ve API kenarında net doğrulama.

İleride shard'lama veya çok bölgeli yapı olacaksa ne seçmeliyim?

UUID'ler dağıtık veya çok-yazarlı kurulumlarda kolaydır çünkü herhangi bir düğüm merkezi bir sıraya sormadan benzersiz ID üretebilir. Bigint ise çalışabilir ama bir plan gerektirir: shard başına aralık ayırma, shard ön eki veya Snowflake benzeri bir jeneratör gibi. UUID en basit dağıtık hikâyeyi sağlar (tercihen zaman sıralı bir versiyon).

Bigint'ten UUID'ye (veya tersi) geçiş ne kadar zahmetlidir?

Birincil anahtar türünü değiştirmek yalnızca tek bir sütunu etkilemez; yabancı anahtarlar, join tabloları, API sözleşmeleri, istemci depolamaları, cache'ler, analytics olayları ve entegrasyonlar etkilenir. Eğer değişebileceğini düşünüyorsanız kademeli bir geçiş planlayın: yeni ID sütunu ekleyin, çift-yazma yapın, eski satırları parti parti doldurun ve uzun bir geçiş penceresi planlayın.

İkisini birlikte kullanabilir miyim: dahili bigint ve harici UUID?

Evet. İç veritabanı verimliliği için dahili bir bigint anahtar tutup, URL'ler ve dış API'ler için ayrı bir public UUID (veya token) ekleyebilirsiniz. Bu, kompakt indeksler ve operasyonel hata ayıklama kolaylığı sağlar; aynı zamanda halka açık kimliklerin kolayca sıralanmasını engeller. Anahtar, hangi tanımın “public ID” olduğunu erken belirlemek ve karıştırmamaktır.

Başlaması kolay
Harika bir şey yaratın

Ücretsiz planla AppMaster ile denemeler yapın.
Hazır olduğunuzda uygun aboneliği seçebilirsiniz.

Başlayın