Birincil anahtar olarak UUID veya GUID kullanmanın sakıncaları nelerdir?


60

Dağıtılmış bir sistem kurmak istiyorum. Verileri veritabanlarında depolamam gerekiyor ve bazı tablolarda birincil anahtar olarak bir UUID veya GUID kullanmak yardımcı olacaktır . UUID / GUID oldukça büyük ve neredeyse rasgele olduklarından bu tasarımın bir dezavantajı olduğunu düşünüyorum. Alternatif, otomatik artan bir INT veya LONG kullanmaktır.

Tablolarım için birincil anahtar olarak UUID veya GUID kullanmanın sakıncaları nelerdir?

Muhtemelen Derby / JavaDB (istemcilerde) ve PostgreSQL'i (sunucuda) DBMS olarak kullanacağım.


Neden yardımcı olsun ki? En çok hangi dezavantajlara odaklandınız? Her DB Sorusunun cevabı bu belirsizliğin “bağlıdır”. Bize daha fazla ayrıntı verebilir misin? En çok okuma veya yazma performansı ile ilgileniyor musunuz? Ne tür bir dağıtımdan bahsediyoruz?
Brian Ballsun-Stanton

@Brian: Dağıtık sistemlerdeki UUID'ler, istemcilerde birincil anahtarı oluşturabileceğiniz ve ardından verileri sunucuya zaman uyumsuz olarak yükleyebileceğiniz için yararlıdır. Çoğunlukla performans okuma dezavantajları hakkında düşünüyorum. UUID'lerde birçok JOIN kullanmak belki de iyi değil mi? Örneğin bir müşteri bir envanter sistemine bir öğe (UUID, isim, tedarikçi, yaratıcı) ekler ve ardından yerel veri tabanı sunucudaki merkezi veri tabanı ile senkronize edilir.
Jonas

1
Bu konuda daha fazla açıklayıcı yorumlar olmadan en çok "bağlı" olacağını düşünüyorum. Bunlar olmadan VtC'ye gidiyorum.
jcolebrand

GUID'e karşı GUID ile ilgili olmayan, SQL Server'daki kümelenmiş dizinler üzerinde farklı bir SQL ürünüyle alakalı olsa bile ilginç bulabileceğiniz bir makale var: x.co/Twpp
Jeff

Derby doc'un UUID'yi veri türü olarak listelemediğini fark ettim . UUID veri türünü listeleyen H2 Veritabanı Altyapısı (Derby gibi saf bir Java veritabanı) gibi bir alternatif düşünebilirsiniz . Elbette Postgres, UUID değerlerini verimli bir şekilde depolamak , endekslemek ve üretmek için mükemmel bir desteğe sahiptir .
Basil Bourque

Yanıtlar:


29

Bu sizin üretim fonksiyonunuza ve final tablolarının boyutuna bağlıdır

GUID'lerin genel olarak benzersiz tanımlayıcıları olması amaçlanmıştır . Postgres 8.3 dokümantasyonunda tartışıldığı gibi, bu tanımlayıcıları oluşturmak için evrensel olarak uygun metodolojiler yoktur, ancak postgreSQL birkaç faydalı aday daha sunar.

Sorununuzun kapsamı ve çevrimdışı yazma gereksinimi açısından , bir GUID'den başka bir şeyin kullanımını oldukça iyi bir şekilde kutuya koydunuz ve bu nedenle diğer programların telafi edici avantajları yok.

İşlevsel bir bakış açısından, anahtar uzunluğu genellikle, tablonun okuma sayısına ve boyutuna bağlı olarak, herhangi bir modern sistemde bir sorun değildir. Alternatif bir metodoloji olarak, çevrimdışı istemciler birincil anahtar olmadan yeni kayıtları toplayabilir ve yeniden bağlanırken bunları ekleyebilirler. PostgreSQL "Seri" veri tipini sunduğundan, istemcilerin veritabanına basit bir yazma yapabiliyorlarsa kimliklerini belirlemelerine asla gerek kalmayacaktır.


3
Lanet olsun uyu, gittin ve Brian soruyu cevaplasın. Evet, "çevrimdışı güncellemeler" gereksinimi, oradaki bütün kavramı tamamen değiştirdi.
jcolebrand

Muahahahaah! :: bıyıktan kaçan bıyık ::
Brian Ballsun-Stanton

1
Çevrimdışı-yazı ile bile INT kullanmak mümkün olacaktır. Örneğin {Node_ID, Item_ID}, her bir düğümün bir a'ya sahip olduğu iki sütunu kullanmak Node_IDve Item_IDbu, düğüm başına otomatik olarak artırılan bir sütun .
Jonas

@Jonas ~ Evet, bu uygulanabilir. Bununla birlikte, çoğu insanın GUID'leri bile düşünmesinin sebeplerinden biri, içeriğin diğer veritabanlarına küresel olarak ayrılmasıdır. Yani, terimin kendisi orada oldukça QED'dir.
jcolebrand

Master / slave mimarileri veya seyrek bağlantılı müşteriler + ana sunucu mimarileri ile ilgili olarak, master'da global_id (SERIAL) ve slave'ler üzerinde global_id (BIGINT) + local_id (SERIAL) kullanmak uygun olabilir. Slave'ler yerel işlerini local_id kullanarak yaparlar ve ustaya doğru ne zaman yapabileceklerini taahhüt ederler, ana veriyi alır ve köleye döndürdüğü bir global_id verir, köle global_id alanını günceller (sunucuyla veya diğerleriyle konuşmak için referans kullanımı için köleler).
Mihai Stancu

22

Bir tavsiye daha - kümelenmiş dizinin bir parçası olarak asla GUID kullanmayın. GUID'ler sıralı değildir, bu nedenle kümelenmiş dizinin bir parçasıysa, her yeni kayıt eklediğinizde, veritabanının int (bigint) otomatik artması durumunda yerleştirme için doğru yeri bulmak için tüm bellek sayfalarını yeniden düzenlemesi gerekir. sadece son sayfa olurdu.

Şimdi bazı db gerçekleştirmelerine bakacak olursak: 1.) MySQL - birincil anahtarlar, davranışını değiştirme seçeneği olmayan kümelenmişlerdir - tavsiye, GUID'leri burada hiç kullanmamaktır 2.) Postgres, MS-SQL - GUID olarak yapabilirsiniz birincil anahtar kümelenmemiş ve kümelenmiş dizin olarak başka bir alan kullanın; örneğin, autoincrement int.


Postgres için önerdiğiniz şey, biraz farklı bir yapıya sahip olan MySQL'de de yapılabilir - auto_increment PK (kümelenmiş anahtar), benzersiz dizine sahip GUID (kümelenmemiş).
ypercubeᵀᴹ

Bu her zaman doğru değildir. Disk sistemi çıkışına bağlı olarak, bu son sayfaya erişimi senkronize etmek sizin darboğazınız olabilir. blog.kejser.org/2011/10/05/…
mwilson

2
"Microsoft SQL Server'dan farklı olarak, PostgreSQL'de bir dizine kümelemek bu sırayı korumaz. Sırayı korumak için CLUSTER işlemini yeniden uygulamanız gerekir." CLUSTER ON endeks performansını nasıl
artırıyor

Bilgileri @ bartolo-otrit'in daha yoğunlaştırılmış bir versiyonu: stackoverflow.com/a/4796685/1394393 . Bu cevap benimle alakalı görünmüyor, çünkü bu soru PG ile ilgili ve mevcut olmayan SQL Server ve MySQL ile benzerlikler varsayıyor gibi görünüyor.
jpmc26

database would need to rearrange all its memory pages to find the right place for insertion=> Postgres ile durum böyle değil, kümelenme isteğe bağlı ve yeni satırlar sıralanmamış olarak depolanıyor.
Flavien

3

Değişir.

Cidden, şu ana kadar verdiğin her şeyle, gidebildiğin kadarıyla ilgili.

UUID'leri kullanmak neden faydalı olabilir? Neden INT kullanmıyorsun? Neden daha sonra UUID’leri endeksleyemiyorsunuz? Bir UUID'nin anahtarıyla sıralanmış bir listeye sahip olmanın ve birkaç milyon satırdan sonra rasgele (sıralı olmayan) bir UUID eklemenin ne anlama geldiğini biliyor musunuz?

Bu hangi platform üzerinde çalışacak? Kaç tane disk Kaç kullanıcı Kaç tane kayıt var


7
Yorumumda yazdığım gibi, UUID kullanırsam istemciler sunucuya bağlantı olmadan veritabanına satır ekleyebilir ve daha sonra sunucu ile senkronize edilebilir. Birincil anahtar için INT'ler kullanırsam bunu yapamam, çünkü birden çok istemci farklı öğeler için aynı birincil anahtarı kullanabilir. Listeyi bir UUID sütununda sıralamak işe yaramazsa, zaman damgası sütununda sıralamak daha yararlı olur. Hayır, birkaç milyon satırdan sonra rasgele sıralı olmayan bir UUID eklemenin ne demek olduğunu bilmiyorum, bu yüzden bu soruyu soruyorum.
Jonas

Uygulama Java dilinde yazılacak ve müşteriler Windows, Mac veya Linux kullanıyor. İstemciler genellikle bir diske sahip olan genel masaüstü bilgisayarları kullanır. Kullanıcı ve kayıt sayısı, kaç müşteriye sahip olduğuma bağlı, ancak müşteri ve müşteri başına yaklaşık 5000 olacak.
Jonas

1
Çevrimdışı yorum her şeyi değiştirdi. Daha ne kadar ayrıntı görüyor musun?
jcolebrand
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.