Zeichenfolgen als Primärschlüssel in der SQL-Datenbank

178

Ich bin nicht sehr vertraut mit Datenbanken und den Theorien, wie sie funktionieren. Ist es unter Leistungsgesichtspunkten (Einfügen / Aktualisieren / Abfragen) langsamer, Zeichenfolgen für Primärschlüssel als Ganzzahlen zu verwenden?

Hauptstränge
quelle

Antworten:

190

Technisch gesehen ja, aber wenn eine Zeichenfolge als Primärschlüssel sinnvoll ist, sollten Sie sie wahrscheinlich verwenden. Dies hängt alles von der Größe der Tabelle ab, für die Sie sie erstellen, und von der Länge der Zeichenfolge, die der Primärschlüssel sein soll (längere Zeichenfolgen == schwerer zu vergleichen). Ich würde nicht unbedingt eine Zeichenfolge für eine Tabelle verwenden, die Millionen von Zeilen enthält, aber die Leistungsverlangsamung, die Sie durch die Verwendung einer Zeichenfolge für kleinere Tabellen erhalten, ist für die Kopfschmerzen, die Sie durch eine Ganzzahl haben können, die dies nicht tut, winzig bedeutet nichts in Bezug auf die Daten.

kemiller2002
quelle
11
würde es nicht von der Datenbank abhängen? Ich würde denken, eine richtig indizierte Zeichenfolge wäre nicht viel langsamer, wenn überhaupt von einer Zahl?
Ryan Guill
2
Ich würde zustimmen, dass es viele Variablen gibt, die berücksichtigt werden müssen. (In sqlserver) Wir haben echte Leistungsprobleme bei der Verwendung von Zeichenfolgen mit Längen im mittleren bis hohen Teenageralter und darüber gesehen, selbst wenn sie indiziert sind. Kaufen Sie haben Recht, es gibt Dinge, die diese Hardware zum Beispiel überwinden können.
kemiller2002
1
Meinetwegen. Ich würde jedoch zustimmen, dass Sie eine Zeichenfolge verwenden sollten, wenn sie sinnvoll ist. Ich würde auch sagen, dass es definitiv Zeiten für GUID- oder UUID-Felder in Datenbanken gibt, in denen ein Autoincrement-Feld nicht funktionieren würde.
Ryan Guill
7
Denken Sie auch daran, dass es bei Indexvergleichen oft einen sehr großen Unterschied zwischen einem CHAR und einem VARCHAR gibt
Tom H
7
Die Anzahl der Kommentare dieser Antwort macht deutlich, wie unvollständig sie ist. Die Erwähnung der Indizierung wäre die minimal akzeptable Antwort gewesen.
Pedro Rolo
74

Ein weiteres Problem bei der Verwendung von Strings als Primärschlüssel besteht darin, dass der Index beim Erstellen eines neuen Schlüssels, der sich in der Mitte der Reihenfolge befindet, neu sequenziert werden muss, wenn der Index ständig in sequenzielle Reihenfolge gebracht wird. Wenn Sie ein Auto verwenden Zahl Ganzzahl, der neue Schlüssel wird gerade am Ende des Index hinzugefügt.

Jeff Martin
quelle
2
Dies kann jedoch zu "Hot Spots" für neue Einsätze führen. Solange Sie Ihre Datenbank ordnungsgemäß verwalten, sollten Sie auf Ihren Seiten ohnehin zusätzlichen Platz für Einfügungen haben und Seitenaufteilungen sollten selten sein.
Tom H
20
In diesem Fall werden Primärschlüssel geclustert. Sie können sie auch ohne Cluster erstellen.
Lernen
Es werden XIDs bestellt, die hilfreich sein können, wenn Sie nur XID-Zeichenfolgen verwenden
Sinaesthetic
22

Einfügungen in eine Tabelle mit einem Clustered-Index, bei der die Einfügung in der Mitte der Sequenz erfolgt, bewirken NICHT, dass der Index neu geschrieben wird. Die Seiten mit den Daten werden nicht neu geschrieben. Wenn auf der Seite, auf der die Zeile abgelegt werden soll, Platz ist, wird sie auf dieser Seite platziert. Die einzelne Seite wird neu formatiert, um die Zeile an der richtigen Stelle auf der Seite zu platzieren. Wenn die Seite voll ist, erfolgt eine Seitenteilung, wobei die Hälfte der Zeilen auf der Seite auf eine Seite und die Hälfte auf die andere Seite verschoben wird. Die Seiten werden dann erneut mit der verknüpften Liste von Seiten verknüpft, die Tabellendaten mit dem Clustered-Index enthalten. Am Ende schreiben Sie höchstens 2 Seiten Datenbank.

Mark Thompson
quelle
Gute Erklärung. Aber gilt dies für alle SQL-Datenbanken? Ich habe von MySQL-Leistungsproblemen bei der Verwendung einer zufälligen UUID als Primärschlüssel gehört.
Hgoebl
13

Saiten sind in Joins langsamer und im wirklichen Leben sehr selten wirklich einzigartig (selbst wenn sie es sein sollen). Der einzige Vorteil besteht darin, dass sie die Anzahl der Verknüpfungen reduzieren können, wenn Sie nur der primären Tabelle beitreten, um den Namen zu erhalten. Zeichenfolgen können sich jedoch häufig ändern, wodurch das Problem entsteht, dass alle zugehörigen Datensätze repariert werden müssen, wenn sich der Firmenname ändert oder die Person heiratet. Dies kann ein großer Leistungseinbruch sein. Wenn alle Tabellen, die in irgendeiner Weise in Beziehung gesetzt werden sollten, nicht in Beziehung stehen (dies passiert häufiger als Sie denken), kann es auch zu Dateninkongruenzen kommen. Eine Ganzzahl, die sich während der gesamten Lebensdauer des Datensatzes niemals ändert, ist sowohl unter dem Gesichtspunkt der Datenintegrität als auch unter dem Gesichtspunkt der Leistung eine weitaus sicherere Wahl. Natürliche Schlüssel sind normalerweise nicht so gut für die Pflege der Daten.

Ich möchte auch darauf hinweisen, dass das Beste aus beiden Welten häufig darin besteht, einen automatisch inkrementierenden Schlüssel (oder in einigen speziellen Fällen eine GUID) als PK zu verwenden und dann einen eindeutigen Index für den natürlichen Schlüssel zu erstellen. Sie erhalten die schnelleren Verknüpfungen, Sie erhalten keine doppelten Datensätze und Sie müssen nicht eine Million untergeordneter Datensätze aktualisieren, da sich ein Firmenname geändert hat.

HLGEM
quelle
26
Zeichenfolgen, die gute Kandidaten für PKs sind, haben keine Duplikate - sonst wären sie kein guter Kandidat für eine PK. Denken Sie an ICD-9-Codes, Ländercodes und Fahrgestellnummern. Die Verwendung eines Namens als Beispiel für ein Problem mit natürlichen Schlüsseln ist falsch, da sie niemals ein Kandidat sein sollten.
Tom H
6
@ Tom H: ISO County Codes ändern sich. [ En.wikipedia.org/wiki/ISO_3166-1#Editions_and_changes ] Als Antwort auf eine Frage im Zusammenhang sagte [ stackoverflow.com/questions/925266/... ] „Für stellen Primärschlüssel sicher ihre Einzigartigkeit ist unter Kontrolle“
Steve Schnepp
4
@SteveSchnepp: Ja, und die ISO ist die vertrauenswürdige Stelle für die Verwaltung dieser Änderung. Auf der anderen Seite, wenn Sie Ihre monotone Folge von inkrementierenden ganzzahligen Werten mit denen eines anderen zusammenführen müssen, sind Sie auf sich allein gestellt;)
am
1
Ich würde zustimmen, dass Namen nicht als Schlüssel betrachtet werden sollten, ich habe gerade viele Male gesehen, als sie waren.
HLGEM
1
@onedaywhen das Zusammenführen von 2 monotonen Sequenzen von inkrementierenden Ganzzahlen ist ganz einfach durch Präfixieren oder Suffixieren möglich :)
Steve Schnepp
6

Es spielt keine Rolle, was Sie als Primärschlüssel verwenden, solange es EINZIGARTIG ist. Wenn Sie Wert auf Geschwindigkeit oder gutes Datenbankdesign legen, verwenden Sie int, es sei denn, Sie möchten Daten replizieren, und verwenden Sie eine GUID.

Wenn dies eine Zugriffsdatenbank oder eine winzige App ist, wen interessiert das dann wirklich? Ich denke, der Grund, warum die meisten von uns Entwicklern das alte Int oder Guid in den Vordergrund stellen, liegt darin, dass Projekte auf uns wachsen und Sie sich die Möglichkeit lassen möchten, zu wachsen.

Al Katawazi
quelle
5

Zu viele Variablen. Dies hängt von der Größe der Tabelle, den Indizes und der Art der String-Schlüsseldomäne ab.

Im Allgemeinen sind Ganzzahlen schneller. Aber wird der Unterschied groß genug sein, um sich darum zu kümmern? Es ist schwer zu sagen.

Was ist Ihre Motivation für die Auswahl von Saiten? Numerische Auto-Inkrement-Tasten sind oft auch viel einfacher . Ist es Semantik? Bequemlichkeit? Replikation / getrennte Bedenken? Ihre Antwort hier könnte Ihre Möglichkeiten einschränken. Dies erinnert auch an eine dritte "Hybrid" -Option, die Sie vergessen: Guids.

Joel Coehoorn
quelle
das macht keinen sinn cloutierm, was meinst du?
HLGEM
@HLGEM: Wenn ich verstehe, dass er schreibt, meint er das Synchronisieren von auf einem Laptop erstellten Datensätzen mit der Hauptdatenbank.
Joel Coehoorn
Ich meine, ich habe zwei separate Datenbanken mit denselben Entitäten, nur eine wird für dauerhafte Speicherzwecke weniger häufig aktualisiert. Wenn ich nach Entität "California" in Datenbank A
frage
1
Und es ist so, als würde man Datensätze synchronisieren, die in einem Laptop erstellt wurden, da es dasselbe Problem ist: Datensätze, die an einem Ort erstellt wurden, sollten nicht mit Datensätzen in Konflikt stehen, die an einem anderen Ort erstellt wurden. Eine mögliche Lösung sind hier Guid-Schlüssel.
Joel Coehoorn
5

Sorgen Sie sich nicht um die Leistung, bis Sie ein einfaches und solides Design erhalten haben, das mit dem in den Daten beschriebenen Thema übereinstimmt und gut zur beabsichtigten Verwendung der Daten passt. Wenn dann Leistungsprobleme auftreten, können Sie diese beheben, indem Sie das System optimieren.

In diesem Fall ist es fast immer besser, eine Zeichenfolge als natürlichen Primärschlüssel zu verwenden, vorausgesetzt, Sie können ihr vertrauen. Machen Sie sich keine Sorgen, wenn es sich um eine Zeichenfolge handelt, solange die Zeichenfolge relativ kurz ist, z. B. maximal 25 Zeichen. Sie zahlen keinen hohen Preis für die Leistung.

Geben die Dateneingabepersonen oder automatischen Datenquellen immer einen Wert für den vermeintlichen natürlichen Schlüssel an oder wird er manchmal weggelassen? Ist es gelegentlich falsch in den Eingabedaten? Wenn ja, wie werden Fehler erkannt und behoben?

Können die Programmierer und interaktiven Benutzer, die Abfragen angeben, den natürlichen Schlüssel verwenden, um das zu erhalten, was sie wollen?

Wenn Sie dem natürlichen Schlüssel nicht vertrauen können, erfinden Sie einen Ersatz. Wenn Sie einen Ersatz erfinden, können Sie auch eine Ganzzahl erfinden. Dann müssen Sie sich Gedanken darüber machen, ob Sie den Ersatz vor der Benutzergemeinschaft verbergen können. Einige Entwickler, die den Ersatzschlüssel nicht verbargen, bereuten es.

Walter Mitty
quelle
3

Indizes implizieren viele Vergleiche.

In der Regel sind Zeichenfolgen länger als Ganzzahlen, und zum Vergleich können Kollatierungsregeln angewendet werden. Daher ist das Vergleichen von Zeichenfolgen normalerweise eine rechenintensivere Aufgabe als das Vergleichen von Ganzzahlen.

Manchmal ist es jedoch schneller, eine Zeichenfolge als Primärschlüssel zu verwenden, als einen zusätzlichen Join mit einer string to numerical idTabelle durchzuführen.

Quassnoi
quelle
2

Ja, aber es sei denn, Sie erwarten Millionen von Zeilen. Wenn Sie keinen stringbasierten Schlüssel verwenden, weil dieser langsamer ist, ist dies normalerweise eine "vorzeitige Optimierung". Schließlich werden Zeichenfolgen als große Zahlen gespeichert, während Zifferntasten normalerweise als kleinere Zahlen gespeichert werden.

Eine Sache, auf die Sie jedoch achten sollten, ist, wenn Sie Indizes auf einem beliebigen Schlüssel gruppiert haben und eine große Anzahl von Einfügungen vornehmen, die im Index nicht sequentiell sind. Jede geschriebene Zeile bewirkt, dass der Index neu geschrieben wird. Wenn Sie Batch-Einfügungen durchführen, kann dies den Prozess erheblich verlangsamen.

Ja - dieser Jake.
quelle
2

Zwei Gründe für die Verwendung von Ganzzahlen für PK-Spalten:

  1. Wir können die Identität für ein ganzzahliges Feld festlegen, das automatisch erhöht wird.

  2. Wenn wir PKs erstellen, erstellt die Datenbank einen Index (Cluster oder Nicht-Cluster), der die Daten sortiert, bevor sie in der Tabelle gespeichert werden. Durch die Verwendung einer Identität in einer PK muss der Optimierer die Sortierreihenfolge nicht überprüfen, bevor ein Datensatz gespeichert wird. Dies verbessert die Leistung an großen Tischen.

Jatinder Singh
quelle
1

Was ist Ihr Grund, eine Zeichenfolge als Primärschlüssel zu haben?

Ich würde einfach den Primärschlüssel auf ein automatisch inkrementierendes Ganzzahlfeld setzen und einen Index für das Zeichenfolgenfeld setzen.

Auf diese Weise sollten Suchvorgänge auf dem Tisch relativ schnell sein, und alle Ihre Verknüpfungen und normalen Suchvorgänge werden in ihrer Geschwindigkeit nicht beeinflusst.

Sie können auch die Größe des Zeichenfolgenfelds steuern, das indiziert wird. Mit anderen Worten, Sie können sagen "Indizieren Sie nur die ersten 5 Zeichen", wenn Sie der Meinung sind, dass dies ausreicht. Wenn Ihre Daten relativ ähnlich sein können, können Sie das gesamte Feld indizieren.

John Bubriski
quelle
3
Ich denke, jede Intelligenz in einen Schlüssel zu stecken, bedeutet Ärger. Werden sie einzigartig bleiben? Haben sie alle Kontonummern mit der Abkürzung des Staates am Anfang nur zum Kundenumzug gestartet? Aktualisiere ein Feld - kein Problem - all diese Tabellen, die durch die Kontonummer verknüpft sind - was für ein Durcheinander.
JeffO
1
Ein Beispiel für die Verwendung einer Zeichenfolge als PK könnte eine Tabelle mit Einstellungen sein. zB settingsNamePK, isUserEditable, isCustomerEditable usw. Wenn Sie dann das Einstellungsverhalten ändern möchten, ist "UPDATE settings SET ... WHERE settingsNamePK = 'dailyWorkObligation'" viel besser, als IDs zu verwenden und die Zuordnung der IDs irgendwo zu speichern. Natürlich könnten Sie eine ganzzahlige PK haben und den Einstellungsnamen auch als einen weiteren eindeutigen Schlüssel haben.
MeatPopsicle
Sollten Einfügungen nicht auch von ihrer Geschwindigkeit unberührt bleiben, da der Primärschlüssel eine automatisch inkrementierte Ganzzahl ist?
Dennis
Für neugierige Rails-Entwickler erfahren Sie hier, wie Sie eine Indexlänge angeben . Beachten Sie, dass SQLite die Indexlänge nicht unterstützt.
Dennis
1

Vom Standpunkt der Leistung aus - Ja, Zeichenfolge (PK) verlangsamt die Leistung im Vergleich zur Leistung, die mit einer Ganzzahl (PK) erzielt wird, wobei PK ---> Primärschlüssel.

Vom Standpunkt der Anforderungen aus - Obwohl dies nicht Teil Ihrer Frage ist, möchte ich noch erwähnen. Wenn wir große Datenmengen über verschiedene Tabellen hinweg verarbeiten, suchen wir im Allgemeinen nach dem wahrscheinlichen Schlüsselsatz, der für eine bestimmte Tabelle festgelegt werden kann. Dies liegt hauptsächlich daran, dass es viele Tabellen gibt und meistens jede oder eine Tabelle durch eine Beziehung (ein Konzept des Fremdschlüssels) miteinander in Beziehung steht. Daher können wir nicht immer eine Ganzzahl als Primärschlüssel auswählen, sondern eine Kombination von 3, 4 oder 5 Attributen als Primärschlüssel für diese Tabellen verwenden. Und diese Schlüssel können als Fremdschlüssel verwendet werden, wenn wir die Datensätze mit einer anderen Tabelle verknüpfen würden. Dies macht es nützlich, die Datensätze bei Bedarf über verschiedene Tabellen hinweg zu verknüpfen.

Daher für eine optimale Verwendung - Wir erstellen immer eine Kombination aus 1 oder 2 Ganzzahlen mit 1 oder 2 Zeichenfolgenattributen, jedoch nur dann, wenn dies erforderlich ist.


quelle
0

Es könnte ein sehr großes Missverständnis im Zusammenhang mit Zeichenfolgen in der Datenbank geben. Fast jeder hat gedacht, dass die Datenbankdarstellung von Zahlen kompakter ist als für Zeichenfolgen. Sie denken, dass in db-s Zahlen wie im Speicher dargestellt werden. ABER es ist nicht wahr. In den meisten Fällen ist die Zahlendarstellung einer Zeichenfolge ähnlicher als einer anderen.

Die Geschwindigkeit der Verwendung von Zahlen oder Zeichenfolgen hängt mehr von der Indizierung als vom Typ selbst ab.

Takacsot
quelle
0

Standardmäßig bestehen ASPNetUserIds aus 128 Zeichenfolgen, und die Leistung ist in Ordnung.

Wenn der Schlüssel HAS in der Tabelle eindeutig sein sollte es der Schlüssel sein. Hier ist der Grund;

Primärzeichenfolgenschlüssel = Richtige DB-Beziehungen, 1 Zeichenfolgenschlüssel (Primär) und 1 Zeichenfolgenindex (Primär).

Die andere Option ist ein typisches int Key, aber wenn die Zeichenfolge HAS eindeutig sein werden Sie wahrscheinlich immer noch brauchen , um einen Index hinzufügen , weil die Non-Stop - Abfragen zu bestätigen oder überprüfen, ob seine einzigartig.

Die Verwendung eines int-Identitätsschlüssels = Falsche DB-Beziehungen, 1 int-Schlüssel (primär), 1 int-Index (primär), wahrscheinlich ein eindeutiger Zeichenfolgenindex und die manuelle Überprüfung derselben Zeichenfolge sind nicht vorhanden (so etwas wie eine SQL-Prüfung möglicherweise ).

Um eine bessere Leistung mit einem int über einen String für den Primärschlüssel zu erhalten, wenn die Zeichenfolge HAS einzigartig sein, müsste es eine sehr seltsame Situation. Ich habe es immer vorgezogen, String-Schlüssel zu verwenden. Und als gute Faustregel sollten Sie eine Datenbank erst denormalisieren, wenn Sie dies benötigen .

JPoole
quelle