Was sind die Kompromisse für das Inkrementieren von IDs gegenüber Volltextschlüsseln für Fremdschlüsselentwürfe?

8

In vielen relationalen Datenbankdesigns gibt es Felder, auf die in anderen Tabellen verwiesen wird.

Betrachten Sie beispielsweise eine Benutzertabelle mit einem eindeutigen Benutzernamen und einer zweiten Tabelle, in der Adressdaten gespeichert sind.

Ein mögliches Layout, das ich sagen würde, ist der übliche Ansatz, den ich in den meisten Programmen beobachtet habe, die Verwendung von Auto-Inkrement-IDs wie folgt:

Table users
===========
userId int primary auto_increment
userName varchar unique

Table adressdata
==========
userId int references users.userId
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userId,adress_type))

So habe ich es gemacht und wie ich es in den meisten Fällen gesehen habe.

Ein anderer Weg wäre:

Table users
===========
userName varchar primary

Table adressdata
==========
userName varchar references users.userName
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userName,adress_type))

Hier speichern wir den vollständigen Benutzernamen auch in der Adressdata-Tabelle.

Für mich hat dies folgende Vorteile:

  • Sie können den Benutzernamen sofort aus der Tabelle auswählen, ohne ihn einer anderen Tabelle hinzufügen zu müssen. In diesem Beispiel ist dies aus Sicht der Anwendung wahrscheinlich nicht so relevant, aber es ist nur ein Beispiel.

  • Es ist möglicherweise einfacher, die Datenbank in einer Master-Master-Replikationsumgebung zu skalieren, da keine Konflikte mit der automatischen Inkrementierung vorliegen.

Aber auch die Nachteile:

  • Der Platzbedarf für den Index und die Daten (aber relevanter wird wahrscheinlich der Index sein) für das Feld in der zweiten Tabelle ist höher.
  • Eine Änderung des Benutzernamens müsste an alle Tabellen weitergegeben werden. Dies ist ressourcenintensiver als nur das Ändern in einer Tabelle und das Beibehalten der IDs.

Meiner Meinung nach ist es viel einfacher, mit Textfeldern zu arbeiten und keine Inkrement-IDs zu verwenden, und die Kompromisse sind minimal und in den meisten Anwendungen nicht relevant.

Natürlich werden einige Objekte aufgrund ihrer Art mit einer inkrementierenden Nummer identifiziert (z. B. sollten Forenbeiträge eine inkrementierende ID erhalten, da es wahrscheinlich kein anderes eindeutiges Feld wie den Titel oder so gibt).

Bevor ich jedoch anfange, meine Datenbanklayouts ganz anders zu gestalten, möchte ich wissen, ob es Dinge gibt, an die ich nicht gedacht habe.

  • Gibt es Best Practices?

  • Gibt es Vor- / Nachteile, an die ich nicht gedacht habe und deren Auswirkungen zu einem späteren Zeitpunkt auftreten können?

  • Wie gestalten Sie persönlich Datenbanken zu den oben genannten Punkten und warum?

Joe Hopfgartner
quelle

Antworten:

3

Ich würde vorschlagen, die ID und nicht den Benutzernamen zu verwenden, da Sie daran denken müssen, alle zu aktualisieren, wenn Sie den Benutzernamen als Verknüpfungsspalte in mehreren Tabellen verwenden.

Der Fremdschlüssel für die usersTabelle wird zum Primärschlüssel der addressdataTabelle und der Primärschlüssel muss stabil bleiben. Es wird empfohlen, die Primärschlüsselfelder nicht zu ändern. Ein Primärschlüssel muss vorhanden sein, wenn der Datensatz erstellt wird, und muss während der gesamten Lebensdauer des Datensatzes unverändert bleiben.

Wenn Sie weitere Einblicke wünschen Die großartige Primärschlüsseldebatte ist ein großartiger Artikel.

stivlo
quelle
2

Ich bin stark im Lager "benutze keine natürlichen Schlüssel". Das liegt daran, dass ich gesehen habe, wie schwierig es für das System ist, wenn sie aktualisiert werden und praktisch alle natürlichen Schlüssel, die Namen jeglicher Art enthalten, aktualisiert werden.

Datenbanken sind für die Verwendung von Joins optimiert. Ja, Sie können einige Verknüpfungen mithilfe natürlicher Schlüssel speichern, aber die Leistung beeinträchtigt, wenn Sie 1.000.000 Datensätze aktualisieren müssen, da eine Gruppe natürlicher Schlüssel geändert wurde (oder sogar abhängig davon, was gerade passiert), kann dies zu einem massiven Stau führen.

Ich würde natürliche Schlüssel nur unter zwei Bedingungen verwenden:

  1. wenn der Schlüssel garantiert nicht geändert wird (denken Sie an die Fahrgestellnummer des Autos) und
  2. wenn es niemals wiederverwendet wird (selbst eindeutige Dinge wie Telefonnummern und E-Mails sind kein Kandidat für eine PK, da sie wiederverwendet werden, wenn jemand sie nicht mehr verwendet).

Und natürlich sind allzu viele natürliche Schlüssel, die einzigartig sein sollen, nicht. Wenn Sie sich Sorgen um die Replikation machen, können Sie GUIDs verwenden.

HLGEM
quelle
1

Der Wikipedia-Artikel über den Ersatzschlüssel enthält einige interessante Punkte:

  • " Attribute, die eine Entität eindeutig identifizieren, können sich ändern, wodurch die Eignung der natürlichen, zusammengesetzten Schlüssel ungültig wird. " Spätere Einschränkungen von Benutzernamen können beispielsweise vorhandene Schlüssel bei Verwendung des natürlichen Schlüssels ungültig machen, user namewährend dies einen synthetischen Schlüssel nicht beeinträchtigt.
  • " Ersatzschlüssel ändern sich nicht, solange die Zeile vorhanden ist. " Daher müssen Sie Schlüsseländerungen nicht (manuell oder automatisch) in Referenztabellen kaskadieren.
  • " Die Werte der generierten Ersatzschlüssel haben keine Beziehung zur realen Bedeutung der in einer Reihe gespeicherten Daten. " Dies kann die Überwachung erschweren.

Ich glaube, dass der aufmerksame Leser zusätzliche Punkte finden kann, die er berücksichtigen sollte.


quelle
Gute Antwort. Viele natürliche Schlüssel neigen zu Veränderungen. Dies macht sie ungeeignet für Schlüssel, die als Fremdschlüssel bezeichnet werden können. Es gibt viele Gründe, warum es angebracht ist, die Benutzer-ID eines Benutzers zu ändern.
BillThor
1

Ich werde aus meiner Erfahrung posten, die sich wahrscheinlich stark von den verschiedenen DBAs unterscheiden wird. Ich bin hauptsächlich auf eine Mischung aus Leistung und Wartbarkeit ausgerichtet, wenn ich Datenbanken für verschiedene Projekte entwerfe.

Ich würde niemals einen natürlichen Schlüssel als Primärschlüssel verwenden. Besonders wenn ich MySQL / InnoDB benutze. Ich habe immer noch keinen Vorteil bei der Verwendung eines natürlichen Schlüssels gesehen. Normalerweise sehe ich Auswirkungen auf die Leistung, wenn nichts. Ich habe "nie, nie" nur deshalb gewagt, weil natürliche Schlüssel verwendet wurden, um Leistungsfresser für meine Projekte zu erstellen. Surrogate (Integer) war immer eine bessere Wahl. Einige mögen nicht zustimmen, aber wir leben in einer Welt, in der Leistung eine Rolle gegenüber der Theorie spielt.

Wenn es um JOINs geht, versuche ich nicht, sie um jeden Preis zu vermeiden, aber ich tendiere dazu, sie zu optimieren. Ich versuche, den Clustered-Index (Primärschlüssel) von InnoDB so weit wie möglich zu missbrauchen. Wenn JOINs über PKs ausgeführt werden, sind sie extrem schnell. Ich neige auch dazu, FKs zu vermeiden, bei denen sie keinen Sinn ergeben. Ehrlich gesagt würde mir die Datenintegrität beim Verknüpfen von Benutzern und ihren Adressinformationen nicht so viel ausmachen. Ich würde es erzwingen, wenn ich Rechnungen mit Artikeln an Benutzer verknüpfe. Die Überbeanspruchung von FKs ist ein Overkill und ein Albtraum, den man aufrechterhalten muss, nachdem man sich auf alles bezogen hat. Irgendwann müssen sich die Dinge ändern, und wenn MySQL sich ständig über Fehler 150 beschwert, möchten Sie einfach nach Hause gehen.

Sie haben auch die Replikation und die Vermeidung von Konflikten aufgrund der Art von auto_increments erwähnt. Ich hatte ein Projekt, in dem wir eine Anzahl von Datenbanken hatten, in denen Produktverkaufsinformationen gespeichert waren. Die Anzahl der Datenbanken war variabel. Jeden Tag wurden die Datenbanken in eine "Master" -Datenbank repliziert, mit der wir Berichte ausgeführt haben. Ich habe PK-Konflikte vermieden, indem ich aus einem auto_increment-Teil und einem anderen INT-Teil einen zusammengesetzten Primärschlüssel erstellt habe, der den Ort angibt, von dem der Datensatz stammt. Auf diese Weise konnte ich verfolgen, woher die Dinge kamen, und ich habe nichts verloren (Produkte hatten dieselbe ID, nur die Standortkennung wurde geändert).

NB
quelle