Guid vs INT - Was ist besser als Primärschlüssel?


97

Ich lese gerade über Gründe, warum ich etwas benutze oder nicht Guidund int.

intist kleiner, schneller, leicht zu merken, behält eine chronologische Reihenfolge. Und Guidder einzige Vorteil, den ich gefunden habe, ist, dass es einzigartig ist. In welchem ​​Fall Guidwäre a besser als und intund warum?

Von dem, was ich gesehen habe, inthat es keine Mängel außer durch die Anzahlbegrenzung, die in vielen Fällen irrelevant sind.

Warum genau wurde Guiderstellt? Ich denke tatsächlich, dass es einen anderen Zweck hat, als als Primärschlüssel einer einfachen Tabelle zu dienen. (Irgendein Beispiel einer echten Anwendung, die Guidfür etwas verwendet wird?)

Typ (Guid = UniqueIdentifier) ​​unter SQL Server


1
Anstatt primäre Schlüssel, ich glaube , Sie meinen Ersatzschlüssel , dh einen Schlüssel, der nicht der natürliche Schlüssel ist (letzteres ist der Schlüssel , den wir in der realen Welt verwendet werden ). Möglicherweise meinen Sie Clustered-Index.
Tag, wenn der

Denken Sie auch an den Unterschied zwischen (Primär) KEY und INDEX.
Allan S. Hansen


2
" inthat keine Fehler, außer durch die in vielen Fällen irrelevante Anzahl.": In diesem Kontext von INT vs GUID ist die Obergrenze eines vorzeichenbehafteten 32-Bit INTvöllig irrelevant, da die Obergrenze eines vorzeichenbehafteten 64-Bit BIGINTist weit über alle Verwendungszwecke hinaus (noch mehr, wenn Sie mit der Nummerierung an der unteren Grenze beginnen und dies gilt auch für INT) und hat immer noch die halbe Größe einer GUID (8 Bytes statt 16) und ist sequentiell.
Solomon Rutzky

Antworten:


89

Dies wurde in Stack Overflow hier und hier gefragt .

In Jeffs Beitrag wird viel über die Vor- und Nachteile der Verwendung von GUID erklärt.

GUID Pros

  • Einzigartig für jede Tabelle, jede Datenbank und jeden Server
  • Ermöglicht das einfache Zusammenführen von Datensätzen aus verschiedenen Datenbanken
  • Ermöglicht die einfache Verteilung von Datenbanken auf mehrere Server
  • Sie können IDs überall generieren, anstatt einen Roundtrip zur Datenbank durchführen zu müssen
  • Die meisten Replikationsszenarien erfordern ohnehin GUID-Spalten

GUID Cons

  • Es ist satte 4-mal größer als der herkömmliche 4-Byte-Indexwert. Dies kann schwerwiegende Auswirkungen auf die Leistung und den Speicher haben, wenn Sie nicht vorsichtig sind
  • Umständlich zu debuggen ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Die generierten GUIDs sollten teilweise sequenziell sein, um die bestmögliche Leistung zu erzielen (z. B. newsequentialid()unter SQL Server 2005+) und die Verwendung von Clustered-Indizes zu ermöglichen

Wenn Sie sich hinsichtlich der Leistung sicher sind und keine Replikation oder Zusammenführung von Datensätzen planen, verwenden Sie intund legen Sie das automatische Inkrement fest ( Identitäts-Seed in SQL Server ).


20
Ein weiterer Nachteil des GUID-Ansatzes ist, dass Sie ihn nicht als Kennung für Ihren Endbenutzer verwenden können. Erwarten Sie wirklich, dass Ihre Benutzer Ihnen am Telefon mitteilen, dass sie ein Problem mit der Bestellung "BAE7DF4-DDF-3RG-5TY3E3RF456AS10" haben? :)
Brann

3
Wenn Sie keine sequenziellen Guids verwenden und Ihr Primärschlüssel geclustert ist (die SQL Server-Standardeinstellung), werden alle Ihre Dateneinfügungen zufällig in der Tabelle verteilt, was zu einer massiven Fragmentierung Ihrer Daten führt. Dies setzt voraus, dass die Daten normalerweise in einer bestimmten Reihenfolge, z. B. chronologisch, eingefügt werden.
Datum

6
Sequentielle Guids sind nur sequentiell, bis die SQL-Instanz neu gestartet wird. Dann wird der erste Wert aufgrund der Art und Weise, wie der Stammwert generiert wird, höchstwahrscheinlich niedriger sein als der vorherige, was wiederum alle möglichen Probleme verursacht.
Mrdenny

20
@Brann Idealerweise würden Sie Ihre PK-Werte nicht in erster Linie an Endbenutzer weitergeben. Ich weiß, dass dies etwas übliches ist, und das habe ich selbst in der Vergangenheit getan, bevor ich gelernt habe, es nicht zu tun. Da dies jedoch nicht getan werden sollte, ist der spezielle Grund, INT gegenüber GUID zu bevorzugen, nicht gültig.
Solomon Rutzky

2
@ChadKuehn Wahl UNIQUEIDENTIFIERüber , INTda INTeine obere Grenze hat , ist eher schlecht Argumentation da grenzenlos zu sein, während wahr genug, nicht um eine praktische Nutzen. Sie können die effektive Kapazität von a leicht verdoppeln, INTindem Sie es an der unteren Grenze (-2,14 Milliarden) anstelle von 1 starten. Wenn die vollen 4,3 Milliarden nicht ausreichen, beginnen Sie mit a BIGINT, das sind immer noch nur 8 Bytes im Vergleich zu 16 für die GUID, und es ist sequentiell.
Solomon Rutzky

18

Wenn Sie Ihre Daten mit einer externen Quelle synchronisieren, kann eine dauerhafte GUID viel besser sein. Ein kurzes Beispiel für die Verwendung von GUIDs ist ein Tool, das an den Kunden gesendet wird, um sein Netzwerk zu crawlen und bestimmte Klassen der automatischen Erkennung durchzuführen, die gefundenen Datensätze zu speichern und dann alle Kundendatensätze in eine zentrale Datenbank zu integrieren zurück zu unserem Ende. Wenn wir eine Ganzzahl verwenden würden, hätten wir 7.398 "1", und es wäre viel schwieriger zu verfolgen, welche "1" welche war.


3
GUIDs eignen sich definitiv als externe Bezeichner, und ich würde einen nicht gruppierten Index davon als "externen Schlüssel" beibehalten. Ich würde weiterhin ein int als "internen Schlüssel" beibehalten, der die Grundlage für die Beziehungen zwischen gruppiertem Index und Fremdschlüsseln darstellt. Wenn etwas eine architektonische Grenze überschreitet (z. B. die Kommunikation mit einer anderen App), schätze ich etwas, das nicht verwechselt werden kann.
Greg

15

Ich habe einen hybriden Ansatz mit Erfolg verwendet. Tabellen enthalten sowohl eine Auto-Inkrement-Primärschlüssel-Ganzzahl- idSpalte als auch eine guidSpalte. Das guidkann nach Bedarf verwendet werden, um die Zeile global eindeutig zu identifizieren, und idkann für Abfragen, Sortieren und menschliche Identifizierung der Zeile verwendet werden.


3
Welchen Wert gibt die GUID an, wenn die idbereits für Menschen ausreicht, um eine Zeile zu identifizieren?
Martin Smith

6
Die ID identifiziert die Zeile in dieser Tabelle. Die GUID identifiziert (zumindest theoretisch) diese Zeile an einer beliebigen Stelle im bekannten Universum. In meinem Projekt haben Android-Handys jeweils eine strukturell identische Kopie der Tabelle in einer lokalen SQLite-Datenbank. Die Zeile und ihre GUID werden jeweils auf Android generiert. Wenn Android dann mit der Back-End-Datenbank synchronisiert wird, wird seine lokale Zeile in die Back-End-Tabelle geschrieben, ohne dass Konflikte mit Zeilen auftreten, die mit einem anderen Android-Handy erstellt wurden.
Rmirabelle

2
@MartinSmith Ich habe diesen Ansatz selbst verwendet und es funktioniert ganz gut. Die GUID ist nur ein alternativer Schlüssel mit einem NonClustered-Index und wird von der Anwendung übergeben, befindet sich jedoch nur in der Primärtabelle. Alle zugehörigen Tabellen sind über die INTPK verknüpft . Ich finde es seltsam, dass dieser Ansatz nicht viel verbreiteter ist, da er das Beste aus beiden Welten ist. Es scheint, als ob die meisten Leute es vorziehen, Probleme in absolutistischen Begriffen zu lösen, ohne zu wissen, dass die PK keine GUID sein muss, damit die App weiterhin GUIDs für globale Eindeutigkeit und / oder Portabilität verwendet.
Solomon Rutzky

1
@rmirabelle Ich hatte über diesen Ansatz nachgedacht und zögerte, aber Ihre Antwort hat mich überzeugt. Grundsätzlich bin ich in einer Situation, in der ich eine eindeutige Kennung für ein Arbeitselement benötigen muss (das von überall über das Netzwerk eingehen kann), aber ich möchte nicht zuerst einen Roundtrip zur Datenbank durchführen. GUIDs sind hierfür eine gute Lösung, aber ich stelle mir vor, dass JOINs viel langsamer werden, wenn ich keinen sequenziellen Clustered Key habe.
easuter

1
@easuter Ich bin damit einverstanden, keine ID-Felder "nur aus Gründen" hinzuzufügen, z. B. in vielen-zu-vielen "Bridge" -Tabellen, in denen die PK aus den beiden verknüpften FKs zusammengesetzt sein sollte. Aber hier handelt es sich nicht um einen Kompromiss, da das ID-Feld nicht nur dazu dient. Es ist ziemlich wichtig, dass das System effizient arbeitet ;-). UND, ich würde argumentieren, dass in Ihrem Fall, da die GUIDs extern generiert werden, diese nicht garantiert eindeutig sind, auch wenn sie pragmatisch sind. Aber die Verantwortung für die Datenintegrität ist Grund genug, GUID ein alternativer Schlüssel und ID in Ihrem Fall PK zu sein :)
Solomon Rutzky

1

In einigen Best Practices wird immer noch erwähnt, dass Sie einen Datentyp verwenden sollten, der den gesamten Wertesatz, den Sie verwenden möchten, so wenig Speicher wie möglich belegt. Wenn Sie beispielsweise damit die Anzahl der Arbeitgeber in einem kleinen Unternehmen speichern und es unwahrscheinlich ist, dass Sie eine 100 erreichen, würde niemand vorschlagen, einen Bigint-Wert zu verwenden, während Int (auch Smallint) dies tun würde.

Der Nachteil dabei ist natürlich "Sag nein zur Skalierbarkeit!"


Ich weiß auch, dass dies nicht völlig verwandt ist, aber es gibt noch einen weiteren Faktor. Wenn es nicht übermäßig ist, versuche ich normalerweise, die Verwendung eines nicht automatisch generierten Primärschlüssels zu empfehlen, falls dies sinnvoll ist. Wenn Sie beispielsweise die Fahrerinformationen speichern, müssen Sie keine neue automatisch generierte Spalte für "ID" erstellen. Verwenden Sie einfach die Lizenznummer.

Ich weiß, das hört sich sehr offensichtlich an, aber ich sehe, dass es ziemlich oft vergessen wird.

Zum Kontext: Dieser Teil der Antwort wurde von einem datentheoretischen Ansatz aus angesprochen, bei dem Ihre PK die eindeutige Datenkennung für einen Datensatz sein soll. In den meisten Fällen erstellen wir diese, wenn sie bereits vorhanden sind, daher die vorherige Antwort.

Es kommt jedoch sehr selten vor, dass Sie die Kontrolle über diese Datenpunkte behalten. Daher müssen Sie möglicherweise Korrekturen oder Anpassungen vornehmen. Sie können das nicht mit Primärschlüsseln machen (nun, Sie können, aber es kann ein Schmerz sein).

Danke @VahiD für die Klarstellungen.


Die Verwendung von aussagekräftigen Primärschlüsseln wird überhaupt nicht empfohlen. Beachten Sie folgendes Szenario: Jemand hat eine falsche Lizenznummer eingegeben und Sie haben diese ID in 3-4 Tabellen als Fremdschlüssel verwendet. Wie können Sie diesen Fehler beheben? Das einfache Bearbeiten der Lizenznummer kann in diesem Fall nicht ausreichen.
VahiD

1
Witzig: Ich habe Ihren Kommentar gelesen und dachte: "Ja, natürlich". Dann habe ich meine Antwort gelesen und dachte: "Habe ich das gesagt?" Komisch, wie sich die Dinge in ein paar Jahren ändern. Ich stamme wahrscheinlich aus einem theoretischeren Umfeld, aber wenn Sie nicht die Kontrolle darüber haben (selten), ist dies nicht sehr nützlich. Ich werde die Antwort aktualisieren.
Alpha

upvote für die Entwicklung in den Jahren :)
VahiD

1

Durch die Verwendung von Auto-Inkrement-IDs können Informationen zu Ihrer Geschäftsaktivität verloren gehen. Wenn Sie einen Shop betreiben und order_iddamit einen Einkauf öffentlich identifizieren, kann jeder Ihre monatliche Anzahl von Verkäufen durch einfache Arithmetik herausfinden.


0

Eine andere Sache, wie GUIDs generiert werden. mrdenny wies richtig darauf hin, dass ein Neustart der Instanzen, selbst wenn newsequentialid () verwendet wird, dazu führt, dass neue Werte mit den "Löchern" beginnen, die bei der vorherigen Verarbeitung zurückgelassen wurden. Eine andere Sache, die "sequentielle" GUIDs betrifft, ist die Netzwerkkarte. Wenn ich mich richtig erinnere, wird die UID der Netzwerkkarte als Teil des GUID-Algorithmus verwendet. Wenn eine Netzwerkkarte ersetzt wird, gibt es keine Garantie dafür, dass die UID einen höheren Wert aufweist, um den sequentiellen Aspekt der Dinge beizubehalten. Ich bin mir auch nicht sicher, wie sich mehrere Netzwerkkarten auf die Zuweisung von Werten mithilfe des Algorithmus auswirken könnten.

Nur ein Gedanke und ich hoffe, ich erinnere mich richtig. Ich wünsche ihnen einen wunderbaren Tag!


2
Willkommen bei den Datenbankadministratoren, bobo8734. Können Sie Quellen für diese Kommentare finden? Wenn Sie sich nicht sicher sind, sind sie möglicherweise besser als Kommentar (wenn Sie den Repräsentanten dafür haben) als als eigenständige Antwort zu verstehen.
LowlyDBA

-6

Verwende beide

Verwenden Sie int / Bigint für Primärschlüssel, da es einfach zu pflegen und als Fremdschlüsselbeziehungen zu verwenden ist.

Binden Sie jedoch eine Spalte an die GUID, sodass jede Zeile auch eine eindeutige Spalte hat


2
Ihre Argumentation für diesen Vorschlag zu erklären, würde bestimmt niemanden verletzen.
Andriy M

GUID ist 36 Zeichen lang wird schwer zu lesen sein, wenn Sie nach einem bestimmten Fall suchen ..
Abdul Hannan Ijaz

1
In Ordnung, aber das erklärt nicht wirklich, warum das OP beide intund verwenden sollte guid, wie Sie in Ihrer Antwort vorschlagen. Außerdem ging es mir nicht darum, Ihren Vorschlag nur mir zu erklären. Mein Punkt war, dass Sie Ihre Antwort möglicherweise aktualisieren möchten . Ist Ihnen übrigens bewusst, dass ein anderer Antwortender bereits dasselbe (mehr oder weniger) vorgeschlagen hat wie Sie ?
Andriy M

Yup ich meinte das gleiche .. cool BTW :)
Abdul Hannan Ijaz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.