Guid vs INT - Który jest lepszy jako klucz podstawowy?

97

Ja będąc czytanie wokół powody do używania lub nie Guidi int.

intjest mniejszy, szybszy, łatwy do zapamiętania, zachowuje sekwencję chronologiczną. A jeśli chodzi o Guid, jedyną zaletą, którą znalazłem, jest to, że jest wyjątkowa. W którym przypadku Guidbyłoby lepiej niż inti dlaczego?

Z tego, co widziałem, intnie ma żadnych wad poza limitem liczbowym, który w wielu przypadkach jest nieistotny.

Dlaczego dokładnie został Guidstworzony? Myślę, że ma inny cel niż służenie jako klucz podstawowy prostej tabeli. (Każdy przykład prawdziwej aplikacji używającej Guidczegoś?)

(Guid = UniqueIdentifier) ​​typ na serwerze SQL

BrunoLM
źródło
1
Myślę, że zamiast klucza podstawowego masz na myśli klucz zastępczy , czyli klucz, który nie jest kluczem naturalnym (ten ostatni jest kluczem, którego używamy w świecie rzeczywistym). Być może masz na myśli indeks klastrowy.
dniu
Pamiętaj także o różnicy między (Podstawowym) KLUCZEM a INDEKSEM.
Allan S. Hansen
1
Omówiono także na SO: stackoverflow.com/questions/11033435/…
Jon of All Trades
2
intnie ma wad, z wyjątkiem limitu liczb, który w wielu przypadkach jest nieistotny.”: w rzeczywistości, w tym kontekście INT vs GUID, górny limit 32-bitowego ze znakiem INTjest całkowicie nieistotny, biorąc pod uwagę, że górny limit podpisanego 64-bitowy BIGINTznacznie wykracza poza prawie wszystkie zastosowania (tym bardziej, jeśli zaczniesz numerację od dolnego limitu; to samo dotyczy INT) i nadal jest o połowę mniejszy niż identyfikator GUID (8 bajtów zamiast 16) i sekwencyjny.
Solomon Rutzky

Odpowiedzi:

89

Zostało to zadane w przepełnieniu stosu tutaj i tutaj .

Wpis Jeffa wyjaśnia wiele zalet i wad używania GUID.

Zalety GUID

  • Unikalny dla każdej tabeli, każdej bazy danych i każdego serwera
  • Umożliwia łatwe łączenie rekordów z różnych baz danych
  • Umożliwia łatwą dystrybucję baz danych na wielu serwerach
  • Możesz generować identyfikatory w dowolnym miejscu, zamiast przechodzić do bazy danych
  • Większość scenariuszy replikacji i tak wymaga kolumn GUID

Wady GUID

  • Jest to 4 razy większa niż tradycyjna 4-bajtowa wartość indeksu; może to mieć poważne konsekwencje dla wydajności i przechowywania, jeśli nie będziesz ostrożny
  • Uciążliwe do debugowania ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Wygenerowane identyfikatory GUID powinny być częściowo sekwencyjne, aby uzyskać najlepszą wydajność (np. W newsequentialid()SQL Server 2005+) i umożliwić korzystanie z indeksów klastrowych

Jeśli masz pewność co do wydajności i nie planujesz replikować ani scalać rekordów, użyj inti ustaw ją na automatyczny przyrost ( ziarno tożsamości w SQL Server ).

CoderHawk
źródło
20
Inną wadą podejścia GUID jest to, że nie można go użyć jako identyfikatora dla użytkownika końcowego. Czy naprawdę oczekujesz od użytkowników, że powiedzą ci przez telefon, że mają problem z zamówieniem „BAE7DF4-DDF-3RG-5TY3E3RF456AS10”? :)
Brann
3
Jeśli nie używasz sekwencyjnych prowadnic, a klucz podstawowy jest klastrowany (defaul SQL Server), wówczas wszystkie wstawiane dane zostaną losowo rozrzucone po całej tabeli, co prowadzi do ogromnej fragmentacji danych. Zakłada się, że dane byłyby normalnie wstawiane w jakiejś kolejności, na przykład chronologicznej.
datagod
6
Przewodniki sekwencyjne są sekwencyjne tylko do momentu ponownego uruchomienia instancji SQL. Wtedy pierwsza wartość będzie najprawdopodobniej niższa niż poprzednia ze względu na sposób, w jaki generowana jest wartość root, co powoduje różnego rodzaju problemy od nowa.
mrdenny,
20
@Brann Idealnie nie dostaniesz swoich wartości PK użytkownikom końcowym. Wiem, że jest to dość powszechne i jest to coś, co sam zrobiłem w przeszłości, zanim nauczyłem się tego nie robić. Ale ponieważ nie należy tego robić, ten konkretny powód, aby preferować INT zamiast GUID, nie jest prawidłowy.
Solomon Rutzky,
2
@ChadKuehn Wybór UNIQUEIDENTIFIERponad, INTponieważ INTma górną granicę, jest raczej kiepskim rozumowaniem, ponieważ bycie nieograniczonym, choć wystarczająco prawdziwe, nie jest praktyczną korzyścią. Możesz łatwo podwoić efektywną pojemność INT, zaczynając od dolnej granicy (-2,14 miliarda) zamiast od 1. Lub, jeśli pełne 4,3 miliarda nie wystarczy, zacznij od BIGINTwciąż jeszcze 8 bajtów w porównaniu do 16 dla GUID i jest to sekwencyjne.
Solomon Rutzky
18

Jeśli synchronizujesz dane ze źródłem zewnętrznym, trwałe GUID może być znacznie lepsze. Szybki przykład użycia identyfikatorów GUID to narzędzie wysyłane do klienta w celu przeszukiwania sieci i przeprowadzania określonych klas automatycznego wykrywania, przechowywania znalezionych rekordów, a następnie wszystkie rekordy klienta są integrowane w centralnej bazie danych z powrotem na naszym końcu. Gdybyśmy użyli liczby całkowitej, mielibyśmy 7 398 „1” i byłoby znacznie trudniej ustalić, która „1” była która.

TML
źródło
3
Identyfikatory GUID są zdecydowanie dobre jako zewnętrzne identyfikatory, a ja zachowałbym indeks nieklastrowy jako „klucz zewnętrzny”. W dalszym ciągu zachowałbym int jako „klucz wewnętrzny”, który jest podstawą indeksu klastrowanego i relacji klucza obcego. Jeśli coś przekroczy granicę architektoniczną (np. Komunikację z inną aplikacją), doceniam posiadanie czegoś, czego nie można pomieszać.
Greg,
15

Z powodzeniem zastosowałem podejście hybrydowe. Tabele zawierają ZARÓWNO idkolumnę liczb całkowitych z kluczem automatycznym i ORAZ guidkolumnę. guidMogą być stosowane w miarę potrzeb, aby globalnie identyfikowania wiersza i idmogą być stosowane do zapytania, sortowania i ludzki identyfikacja szeregu.

rmirabelle
źródło
3
Jaką wartość ma identyfikator GUID, jeśli idjest już wystarczający, aby ludzie mogli zidentyfikować wiersz?
Martin Smith
6
Identyfikator identyfikuje wiersz w tej tabeli. GUID (przynajmniej teoretycznie) identyfikuje ten wiersz w dowolnym miejscu znanego wszechświata. W moim projekcie telefony komórkowe z Androidem mają strukturalnie identyczną kopię tabeli w lokalnej bazie danych SQLite. Wiersz i jego identyfikator GUID są generowane na Androidzie. Następnie, gdy Android jest zsynchronizowany z bazą danych zaplecza, jego lokalny wiersz jest zapisywany w tabeli zaplecza bez obawy o konflikt z wierszami utworzonymi z dowolnego innego urządzenia z Androidem.
rmirabelle,
2
@MartinSmith Sam zastosowałem to podejście i działa całkiem nieźle. Identyfikator GUID jest tylko kluczem alternatywnym z indeksem nieklastrowanym i jest przekazywany z aplikacji, ale znajduje się tylko w tabeli podstawowej. Wszystkie powiązane tabele są powiązane przez INTPK. Wydaje mi się dziwne, że takie podejście nie jest dużo bardziej powszechne, biorąc pod uwagę, że jest najlepsze z obu światów. Wygląda na to, że większość ludzi po prostu woli rozwiązywać problemy w kategoriach absolutnych, nie zdając sobie sprawy, że PK nie musi być GUID, aby aplikacja mogła nadal używać GUID dla globalnej wyjątkowości i / lub przenośności.
Solomon Rutzky,
1
@rmirabelle Myślałem o tym podejściu i wahałem się, ale Twoja odpowiedź mnie przekonała. Zasadniczo jestem w sytuacji, w której muszę mieć unikalny identyfikator elementu pracy (który może wejść przez sieć z dowolnego miejsca), ale nie chcę najpierw podróżować w obie strony do bazy danych. Identyfikatory GUID są dobrym rozwiązaniem, ale wyobrażam sobie, że DOŁĄCZY staną się znacznie wolniejsze, jeśli nie będę mieć klucza sekwencyjnego.
easuter
1
@easuter Zgadzam się, aby nie dodawać pól identyfikacyjnych „tylko ze względu na to”, takich jak w tabelach „pomostowych” wiele do wielu, w których PK powinno być złożeniem dwóch powiązanych ze sobą FK. Ale tutaj nie jest to kompromis, ponieważ pole identyfikatora nie służy wyłącznie temu. Umożliwienie wydajnego działania systemu jest dość ważne ;-). ORAZ argumentowałbym, że w twoim przypadku, ponieważ identyfikatory GUID są generowane zewnętrznie, nie są one gwarantowane jako unikalne, nawet jeśli są pragmatycznie. Ale odpowiedzialność za integralność danych jest wystarczającym powodem, aby GUID był alternatywnym kluczem, a ID być PK w twoim przypadku :)
Solomon Rutzky
1

Niektóre najlepsze praktyki nadal wspominają, że powinieneś używać typu danych, który przy możliwie najmniejszej ilości pamięci powinien zawierać cały zestaw wartości, których będziesz używać. Na przykład, jeśli używasz go do przechowywania liczby pracodawców w małej firmie i jest mało prawdopodobne, aby dostać się do 100, to nikt nie sugerowałby używania wartości bigint, podczas gdy int (nawet smallint) zrobiłby.

Oczywiście wadą tego jest „powiedz nie skalowalności!”


Wiem też, że nie jest to całkowicie powiązane, ale jest jeszcze inny czynnik. Kiedy nie jest nadmierna, zwykle próbuję zalecić użycie nieautogenicznego klucza podstawowego, jeśli ma to sens. Na przykład, jeśli zapisujesz informacje o sterowniku, nie zawracaj sobie głowy tworzeniem nowej automatycznie generowanej kolumny dla „ID”, po prostu użyj numeru licencji.

Wiem, że to brzmi naprawdę oczywisto, ale widzę to często zapominane.

Dla kontekstu: ta część odpowiedzi została zaadaptowana z teoretycznego podejścia do danych, w którym chcesz, aby PK był unikalnym identyfikatorem danych dla rekordu. Większość razy tworzymy je, gdy już istnieją, stąd poprzednia odpowiedź.

Jednak bardzo rzadko można mieć ścisłą kontrolę nad tymi punktami danych i dlatego może być konieczne wprowadzenie korekt lub korekt. Nie możesz tego zrobić za pomocą kluczy podstawowych (cóż, możesz, ale może to być ból).

Dzięki @VahiD za wyjaśnienia.

Alfa
źródło
używanie znaczących kluczy podstawowych nie jest w ogóle zalecane, rozważ poniższy scenariusz, ktoś wpisał nieprawidłowy numer licencji i użyłeś tego identyfikatora w 3-4 tabelach jako klucz obcy, jak naprawić ten błąd? po prostu edycja numeru licencji nie może być w tym przypadku wystarczająca.
VahiD,
1
Zabawne: przeczytałem twój komentarz i pomyślałem „tak, oczywiście”, potem wróciłem, by przeczytać moją odpowiedź i pomyślałem „czy to powiedziałem”? Zabawne, jak rzeczy się zmieniają za kilka lat. Prawdopodobnie pochodziłem z bardziej teoretycznego tła, ale jeśli nie masz nad tym ścisłej kontroli (rzadko), nie przynosi to większych korzyści. Zaktualizuję odpowiedź.
Alfa
głosowanie za rozwój w latach :)
VahiD
1

Korzystanie z identyfikatorów automatycznego przyrostu może spowodować wyciek informacji o Twojej działalności biznesowej. Jeśli prowadzisz sklep i używasz go order_iddo publicznego zidentyfikowania zakupu, każdy może sprawdzić Twoją miesięczną liczbę sprzedaży za pomocą prostej arytmetyki.

golopot
źródło
0

Kolejna sprawa z tym, jak generowane są identyfikatory GUID. mrdenny poprawnie wskazał, że nawet jeśli używany jest newsequentialid (), ponowne uruchomienie instancji powoduje, że nowe wartości zaczynają się od „dziur” pozostawionych w poprzednim przetwarzaniu. Kolejną rzeczą, która wpływa na „sekwencyjne” GUID, jest karta sieciowa. Jeśli dobrze pamiętam, UID karty sieciowej jest używany jako część algorytmu GUID. Jeśli karta sieciowa zostanie zastąpiona, nie ma gwarancji, że UID będzie miał wyższą wartość, aby zachować sekwencyjny aspekt rzeczy. Nie jestem również pewien, jak wiele kart sieciowych może wpływać na przypisywanie wartości za pomocą algorytmu.

Tylko myśl i mam nadzieję, że dobrze pamiętam. Miłego dnia!

bobo8734
źródło
2
Witamy administratorów baz danych, bobo8734. Czy możesz znaleźć źródła tych komentarzy? Jeśli nie masz pewności co do nich, może lepiej byłoby dla nich podać komentarz (jeśli masz do tego przedstawiciela) niż samodzielną odpowiedź.
LowlyDBA
-6

Używać obu

Użyj int / Bigint dla klucza podstawowego, ponieważ jest łatwy w utrzymaniu i używany jako relacje klucza obcego.

Ale powiąż kolumnę z GUID , aby każdy wiersz miał również unikalną kolumnę

Abdul Hannan Ijaz
źródło
2
Wyjaśnienie twojego uzasadnienia tej sugestii nie zaszkodzi nikomu, jestem pewien.
Andriy M
GUID ma 36 znaków i będzie trudny do odczytania na wypadek, gdybyś szukał konkretnego przypadku.
Abdul Hannan Ijaz
1
W porządku, ale to tak naprawdę nie wyjaśnia, dlaczego PO powinien używać obu inti guid, jak sugerujesz w swojej odpowiedzi. A poza tym nie mówiłem o wyjaśnieniu twojej sugestii tylko dla mnie - miałem na myśli, że możesz chcieć zaktualizować swoją odpowiedź . Nawiasem mówiąc, czy zdajesz sobie sprawę, że inny użytkownik odpowiedział już na to samo (mniej więcej) ?
Andriy M
Tak, miałem na myśli to samo .. fajne BTW :)
Abdul Hannan Ijaz