2008-10-03 9 views
17

Ich entwerfe eine kleine SQL-Datenbank, die von einer Webanwendung verwendet werden kann.Sollte ich ein dediziertes Primärschlüsselfeld haben?

Nehmen wir an, eine bestimmte Tabelle hat ein Namensfeld, für das keine zwei Zeilen den gleichen Wert haben dürfen. Benutzer können das Feld Name jedoch jederzeit ändern.

Der Primärschlüssel aus dieser Tabelle wird in anderen Tabellen als Fremdschlüssel verwendet. Wenn also das Feld Name als Primärschlüssel verwendet wurde, müssten alle Änderungen an diese anderen Tabellen weitergegeben werden. Auf der anderen Seite würde die Eindeutigkeitsanforderung automatisch gehandhabt werden.

Mein Instinkt wäre, ein Integer-Feld hinzuzufügen, um als Primärschlüssel zu fungieren, der automatisch von der Datenbank aufgefüllt werden könnte. Gibt es einen Sinn, dieses Feld zu haben, oder wäre es Zeitverschwendung?

+0

Eine Ausnahme, die normalerweise gefunden wird, ist für 'System' Daten. Das heißt, Sie definieren sich Statusfelder etc .. – ShoeLace

Antwort

25

Ich würde eine generierte PK selbst verwenden, nur aus den von Ihnen genannten Gründen. Außerdem ist das Indizieren und Vergleichen nach Ganzzahlen schneller als das Vergleichen nach Zeichenfolgen. Sie können dem Namensfeld auch einen eindeutigen Index hinzufügen, ohne es zu einem Primärschlüssel zu machen.

+2

Dies ist allgemein die akzeptierte Art der Handhabung von Primärschlüsseln. Sie sollten niemals eine Spalte für Ihren Primärschlüssel auswählen, deren Wert geändert werden kann, da Sie dann in ein Kaskadierungsupdate für alle Tabellen gelangen, die diesen Schlüssel enthalten. –

0

Der Primärschlüssel muss einmalig für jede Zeile sein. Die auto_increment Ganzzahl ist eine sehr gute Idee, und wenn Sie keine anderen Ideen zum Auffüllen des Primärschlüssels haben, dann ist dies der beste Weg.

2

Ja - und als Faustregel immer für jeden Tisch.

Sie sollten definitiv kein veränderbares Feld als Primärschlüssel verwenden und in der überwiegenden Mehrheit der Fälle möchten Sie kein Feld verwenden, das einen anderen Zweck als Primärschlüssel hat.

Dies ist eine grundlegende bewährte Methode für db-Schemas.

2

Haben Sie einen Integer-Primärschlüssel ist immer eine gute Sache aus der Leistungspotential. Alle Ihre Beziehungen werden mit einem ganzzahligen Primärschlüssel viel effizienter sein. Zum Beispiel werden JOINs sehr viel schneller (SQL Server).

Es ermöglicht Ihnen auch zukünftige Änderungen der Datenbank. Ziemlich oft haben Sie eine eindeutige Namensspalte, nur um später herauszufinden, dass der Name überhaupt nicht einzigartig ist.

Jetzt können Sie die Eindeutigkeit der Spalte Name erzwingen, indem Sie einen Index darüber haben.

2

Ich würde ein automatisch generiertes ID-Feld für den Primärschlüssel verwenden. Es ist einfacher, Tabellen mit ganzzahligen IDs als Text zu verknüpfen. Wenn das Feld Name oft aktualisiert wird, würde die Datenbank bei einer Aktualisierung des Indexes auf diesem Feld viel häufiger unter Stress stehen, wenn es sich um einen Primärschlüssel handeln würde.

Wenn das Feld Name immer eindeutig ist, sollten Sie es immer noch als eindeutig in der Datenbank markieren. Allerdings wird es oft die Möglichkeit geben, zwei gleiche Namen zu haben (vielleicht nicht, aber möglicherweise in Zukunft). Ich kann es daher nicht empfehlen.

Ein weiterer Vorteil für die Verwendung von IDs besteht darin, dass Sie eine Berichtsanforderung für Ihre Datenbank haben. Wenn Sie einen Bericht für eine bestimmte Gruppe von Namen haben möchten, bleibt der ID-Filter für den Bericht konsistent, auch wenn sich die Namen ändern.

1

Wenn Sie in den engen Kreisen der theoretischen Mathematiker leben (wie C. Date im Land-wo-dort-sind-keine-Nullen, weil alle Datenwerte bekannt und korrekt sind), dann Primärschlüssel kann aus den Komponenten der Daten gebildet werden, die die idealisierte platonische Entität identifizieren, auf die Sie sich beziehen (dh Name + Geburtstag + Geburtsort + Elternnamen), aber in der unordentlichen realen Welt "synthetische Schlüssel", die Ihre realen identifizieren können Welt Entitäten im Kontext Ihrer Datenbank sind ein viel praktischer Weg, Dinge zu tun. (Und auf NULL festlegbare Felder können sehr nützlich sein. Nehmen Sie das, relational-Design-Theorie Menschen!)

+0

Hoffen wir, dass Celko niemals zu einem Stacker wird oder wir uns alle zu einem großen Dressing hinreißen lassen. –

+0

Oh, wir werden es alle schlecht kriegen, wenn das passiert! –

1

Der Primärschlüssel für einen Datensatz eindeutig sein muss und permanent. Wenn ein Datensatz natürlich einen einfachen Schlüssel hat, der beide erfüllt, dann benutze ihn. Sie kommen jedoch nicht oft vor. Für einen Personendatensatz ist der Name der Person weder eindeutig noch dauerhaft, Sie müssen also ziemlich genau ein Autoinkrement verwenden.

Der einzige Ort, an dem natürliche Schlüssel funktionieren, ist eine Codetabelle, z. B. eine Tabelle, die ihrer Beschreibung einen Statuswert zuordnet. Es ist wenig sinnvoll, "Active" einen Primärschlüssel von 1, "Delay" einen Primärschlüssel von 2 usw. zu geben. Wenn es genauso einfach ist, "Active" einen Primärschlüssel von "ACT" zu geben; "Verzögert", "DLY"; "Auf Halten", "HLD" und so weiter.

Beachten Sie auch, einige sagen, Sie sollten Ganzzahlen über Strings verwenden, weil sie schneller vergleichen. Nicht wirklich wahr. Ein Vergleich von zwei 4-Byte-Zeichenfeldern dauert genau so lang wie der Vergleich von zwei 4-Byte-Ganzzahlfeldern. Eine längere Saite wird natürlich länger dauern, aber wenn Sie die Codes kurz halten, gibt es keinen Unterschied.

+0

Ein anderes Beispiel: 'country_code' (' US', 'UK', etc). Leute neigen dazu, ein 4-Byte "INT" zu verwenden, wenn ein "CHAR (2) CHARACTER SET ascii" nur 2 Bytes benötigt und aus anderen Gründen besser funktioniert. Wenn sich die Tschechoslowakei in die Tschechische Republik und die Slowakei aufspaltete, müssten Sie Code für jedes Primärschlüssel-Design schreiben. –

6

Obwohl es schneller ist, in einer Integer-Spalte zu suchen und sich einer Spalte anzuschließen (wie viele darauf hingewiesen haben), ist es noch schneller, sich nie an erster Stelle zu beteiligen. Durch das Speichern einer natural key können Sie häufig die Notwendigkeit einer Verknüpfung beseitigen.

Für eine kleinere Datenbank hätten die CASCADE-Aktualisierungen für die Fremdschlüsselreferenzen nur geringe Auswirkungen auf die Leistung, es sei denn, sie würden sich extrem häufig ändern.

In diesem Fall sollten Sie wahrscheinlich eine Ganzzahl oder GUID als verwenden. Ein updateable-by-design Primärschlüssel ist nicht die beste Idee, und wenn Ihre Anwendung einen sehr zwingenden Geschäftsgrund hat, um nach dem Namen eindeutig zu sein - Sie werden unvermeidlich Konflikte haben.

1

Wenn sich Ihre Namensspalte ändert, ist sie nicht wirklich ein guter Kandidat für einen Primärschlüssel. Ein Primärschlüssel sollte eine eindeutige Zeile einer Tabelle definieren. Wenn es geändert werden kann, tut es das nicht wirklich. Ohne weitere Einzelheiten über Ihr System zu erfahren, kann ich nicht sagen, aber dies könnte eine gute Zeit für einen Ersatzschlüssel sein.

Ich werde dies auch in der Hoffnung hinzufügen, die Mythen der Verwendung von automatisch inkrementierenden Ganzzahlen für alle Ihre Primärschlüssel zu zerstreuen. Es ist NICHT immer ein Leistungsgewinn, sie zu benutzen. Tatsächlich ist es oft genau das Gegenteil. Wenn Sie eine automatisch inkrementierende Spalte haben, bedeutet dies, dass jede INSERT-Operation im System jetzt einen zusätzlichen Aufwand beim Generieren eines neuen Werts hat.

Auch, wie Mark hervorhebt, mit Ersatz-IDs für alle Ihre Tabellen, wenn Sie eine Kette von Tabellen haben, die verwandt sind, müssen Sie alle diese Tabellen zusammenfügen, um sie zu durchlaufen. Bei natürlichen Primärschlüsseln ist dies normalerweise nicht der Fall. Das Verbinden von 6 Tabellen mit Ganzzahlen ist normalerweise langsamer als das Verbinden von 2 Tabellen mit einer Zeichenfolge.

Sie verlieren auch häufig die Fähigkeit, Set-basierte Operationen auszuführen, wenn Sie IDs für alle Ihre Tabellen automatisch inkrementieren.Anstatt 1000 Zeilen in eine übergeordnete Tabelle einzufügen und dann 5000 Zeilen in eine untergeordnete Tabelle einzufügen, müssen Sie nun die übergeordneten Zeilen nacheinander in einen Cursor oder eine andere Schleife einfügen, um die generierten IDs zu erhalten, damit Sie sie zuweisen können zu den verwandten Kindern. Ich habe gesehen, wie sich ein 30-Sekunden-Prozess in einen 20-Minuten-Prozess verwandelte, weil jemand darauf bestand, automatisch inkrementierende IDs für alle Tabellen in einer Datenbank zu verwenden.

Endlich (zumindest aus Gründen, die ich hier listet - gibt es sicherlich andere), die Verwendung von automatisch inkrementierenden IDs auf allen Ihren Tabellen fördert schlechtes Design. Wenn der Designer nicht mehr darüber nachdenken muss, was ein natürlicher Schlüssel für eine Tabelle sein könnte, führt dies in der Regel dazu, dass fehlerhafte Duplikate in den Daten landen. Sie können versuchen, das Problem mit eindeutigen Indizes zu vermeiden, aber meiner Erfahrung nach werden Entwickler und Designer diese zusätzlichen Anstrengungen nicht durchführen und nach einem Jahr der Verwendung ihres neuen Systems finden sie heraus, dass die Daten ein Chaos sind, weil die Datenbank nicht hatte richtige Einschränkungen für die Daten durch natürliche Schlüssel.

Es gibt sicherlich eine Zeit für Ersatzschlüssel, aber blind auf allen Tischen zu verwenden, ist fast immer ein Fehler.

+0

Beachten Sie, dass die Leistungseinbuße für das Einfügen in übergeordnete und untergeordnete Tabellen nur erforderlich ist, wenn Sie darauf bestehen, übergeordnete, dann untergeordnete, dann übergeordnete und dann untergeordnete Elemente zu erstellen. Erstellen Sie zuerst 1K Eltern und dann die 5K Kinder. –

0

Zusätzlich zu allem, was gesagt wird, betrachten mit einer UUID als PK. Dadurch können Sie Schlüssel erstellen, die uniq über mehrere Datenbanken hinweg umfassen.

Wenn Sie jemals Daten mit einer anderen Datenbank exportieren/zusammenführen müssen, bleiben die Daten immer eindeutig und Beziehungen können einfach verwaltet werden.