Jakie są wady używania UUID lub GUID jako klucza podstawowego?

60

Chciałbym zbudować system rozproszony. Muszę przechowywać dane w bazach danych i pomocne byłoby użycie UUID lub GUID jako klucza podstawowego w niektórych tabelach. Zakładam, że jest to wada tego projektu, ponieważ UUID / GUID jest dość duży i są prawie losowe. Alternatywą jest użycie automatycznego przyrostu INT lub LONG.

Jakie są wady używania UUID lub GUID jako klucza podstawowego dla moich tabel?

Prawdopodobnie użyję Derby / JavaDB (na klientach) i PostgreSQL (na serwerze) jako DBMS.

Jonas
źródło
Dlaczego miałoby to być pomocne? Na jakich wadach najbardziej się koncentrujesz? Odpowiedź na każde pytanie DB, które jest niejasne, brzmi „to zależy”. Czy możesz podać nam więcej szczegółów? Czy najbardziej interesuje Cię odczyt lub zapis? o jakim poziomie dystrybucji mówimy?
Brian Ballsun-Stanton
@Brian: UUID w systemach rozproszonych jest pomocny, ponieważ możesz utworzyć klucz podstawowy na klientach, a następnie asynchronicznie przesłać dane na serwer. Myślę głównie o wadach wydajności odczytu. Używanie wielu JOIN na UUID nie jest może tak dobre? Na przykład klient dodaje element (UUID, nazwę, dostawcę, twórcę) do systemu zapasów, a następnie lokalna baza danych jest synchronizowana z centralną bazą danych na serwerze.
Jonas
1
Myślę, że bez dalszych wyjaśnień na ten temat będzie to co najwyżej „to zależy”. Bez nich wybiorę VtC.
jcolebrand
Jest artykuł, który mówi o wpływie GUID na nie-GUID na indeksy klastrowe w SQL Server, które mogą być interesujące, mimo że są powiązane z innym produktem SQL: x.co/Twpp
Jeff
Zauważyłem, że dokument Derby nie podaje UUID jako typu danych. Warto rozważyć alternatywę, taką jak H2 Database Engine (czysta baza danych Java, taka jak Derby), która zawiera typ danych UUID . Oczywiście Postgres ma doskonałe wsparcie dla wydajnego przechowywania , indeksowania i generowania wartości UUID.
Basil Bourque,

Odpowiedzi:

29

To zależy od funkcji generowania i wielkości końcowych tabel

Identyfikatory GUID mają być unikatowymi na całym świecie identyfikatorami. Jak omówiono w dokumentacji Postgres 8.3, nie ma metodologii, które byłyby ogólnie odpowiednie do generowania tych identyfikatorów, ale postgreSQL jest dostarczany z kilkoma bardziej przydatnymi kandydatami.

Biorąc pod uwagę zakres problemu i potrzebę pisania offline , całkiem zgrabnie ograniczyłeś korzystanie z niczego oprócz GUID, a zatem nie ma żadnych kompensacyjnych zalet innych schematów.

Z funkcjonalnego punktu widzenia długość klucza zwykle nie stanowi problemu w żadnym nowoczesnym systemie, w zależności od liczby odczytów i wielkości stołu. Jako alternatywna metodologia klienci offline mogą grupować nowe rekordy bez klucza podstawowego i po prostu wstawiać je podczas ponownego łączenia. Ponieważ postgreSQL oferuje typ danych „Serial”, klienci nigdy nie będą musieli określać identyfikatora, jeśli będą mogli wykonać prosty zapis do bazy danych.

Brian Ballsun-Stanton
źródło
3
Cholera, śpisz, odszedłeś i pozwoliłeś Brianowi odpowiedzieć na pytanie. Tak, wymóg „aktualizacji offline” całkowicie zmienił tam całą koncepcję.
jcolebrand
Muahahahaah! :: kręci wąsy złowrogo ::
Brian Ballsun-Stanton
1
Nawet przy zapisie offline byłoby możliwe użycie INT. Np. Za pomocą dwóch kolumn, w {Node_ID, Item_ID}których każdy węzeł ma Node_ID, oraz wartość, Item_IDktóra jest automatycznie zwiększana dla każdego węzła.
Jonas
@Jonas ~ Tak, to możliwe. Jednak jednym z powodów, dla których większość ludzi zastanawia się nad identyfikatorami GUID, jest globalnie oddzielona replikacja treści do innych baz danych. Mam na myśli, że sam termin jest tam raczej QED.
jcolebrand
W odniesieniu do architektur master / slave lub architektur połączeń rzadkich + architektur głównego serwera, czy byłoby możliwe użycie global_id (SERIAL) na master i id_globalny (BIGINT) + local_id (SERIAL) na slave. Niewolnicy wykonują swoją pracę lokalną za pomocą identyfikatora lokalnego i zatwierdzają, gdy tylko mogą, w kierunku mastera, master otrzymuje dane i nadaje mu identyfikator globalny, który zwraca do urządzenia slave, a slave aktualizuje pole global_id (w celach informacyjnych w rozmowie z serwerem lub innym niewolnicy).
Mihai Stancu,
22

Jeszcze jedna rada - nigdy nie używaj identyfikatorów GUID jako części indeksu klastrowego. Identyfikatory GUID nie są sekwencyjne, więc jeśli są częścią indeksu klastrowego, za każdym razem, gdy wstawisz nowy rekord, baza danych będzie musiała zmienić układ wszystkich stron pamięci, aby znaleźć odpowiednie miejsce do wstawienia, w przypadku automatycznej inkrementacji int (bigint) byłaby ostatnia strona.

Teraz, jeśli spojrzymy na niektóre realizacje bazy danych: 1.) MySQL - klucze podstawowe są klastrowane, bez opcji zmiany zachowania - zaleca się, aby w ogóle nie używać tutaj identyfikatorów GUID 2.) Postgres, MS-SQL - możesz ustawić GUID jako klucz podstawowy niesklastrowany i użyj innego pola jako indeksu klastrowanego, na przykład autoinkrementacja int.

Ross Ivantsiv
źródło
To, co proponujesz dla Postgres, można również zrobić w MySQL, z nieco inną strukturą - auto_increment PK (klucz klastrowany), GUID z unikalnym indeksem (nieklastrowany).
ypercubeᵀᴹ
To nie zawsze jest prawda. W zależności od przepustowości systemu dyskowego synchronizacja dostępu do tej ostatniej strony może być wąskim gardłem. blog.kejser.org/2011/10/05/…
mwilson
2
„W przeciwieństwie do Microsoft SQL Server, klastrowanie indeksu w PostgreSQL nie utrzymuje tego porządku. Musisz ponownie zastosować proces CLUSTER, aby utrzymać porządek.” W jaki sposób CLUSTER ON poprawia wydajność indeksu
bartolo-otrit
Bardziej skrócona wersja informacji @ bartolo-otrit połączona z: stackoverflow.com/a/4796685/1394393 . Ta odpowiedź nie wydaje mi się istotna, ponieważ to pytanie dotyczy PG i wydaje się, że zakłada podobieństwa do SQL Server i MySQL, które nie istnieją.
jpmc26,
database would need to rearrange all its memory pages to find the right place for insertion=> Nie sądzę, że tak jest w przypadku Postgres, ponieważ klastrowanie jest opcjonalne, a nowe wiersze są przechowywane nieuporządkowane.
Flavien
3

To zależy.

Poważnie, biorąc pod uwagę wszystko, co dotychczas dałeś, jest to tak daleko, jak możesz.

Dlaczego warto korzystać z UUID? Dlaczego nie użyjesz INT? Dlaczego nie możesz później indeksować UUID? Czy rozumiesz, co to znaczy mieć posortowaną listę z kluczem UUID i wstawić losowy (niesekwencyjny) UUID po kilku milionach wierszy?

Na jakiej platformie będzie to działało? Ile dysków? Ilu użytkowników? Ile rekordów?

jcolebrand
źródło
7
Jak napisałem w komentarzu, jeśli używam UUID, klienci mogą dodawać wiersze do bazy danych bez połączenia z serwerem, a następnie synchronizować z serwerem. Nie mogę tego zrobić, jeśli używam INT dla klucza podstawowego, ponieważ wielu klientów może wtedy używać tego samego klucza podstawowego do różnych elementów. Cóż, bezużyteczne jest sortowanie listy według kolumny UUID, bardziej przydatne byłoby posortowanie jej według kolumny znacznika czasu. Nie, nie wiem, co to znaczy wstawić losowy niesekwencyjny UUID po kilku milionach wierszy, dlatego zadaję to pytanie.
Jonas
Aplikacja zostanie napisana w Javie, a klienci używają Windows, Mac lub Linux. Klienci będą korzystać ze zwykłych komputerów stacjonarnych, które zwykle mają jeden dysk. Liczba użytkowników i rekordów zależy od tego, ilu klientów otrzymam, ale będzie to około 5000 na klienta i klienta.
Jonas
1
Komentarz offline zmienił wszystko. Zobacz, co robi więcej szczegółów?
jcolebrand