Ist es empfehlenswert, immer einen Autoincrement Integer-Primärschlüssel zu haben?

191

In meinen Datenbanken habe ich die Gewohnheit, idfür jede Tabelle, die ich erstelle , einen sich automatisch inkrementierenden, ganzzahligen Primärschlüssel mit dem Namen zu verwenden, damit ich eine eindeutige Suche nach einer bestimmten Zeile durchführen kann.

Ist das eine schlechte Idee? Gibt es irgendwelche Nachteile, wenn man es so macht? Manchmal habe ich mehrere Indizes, z. B. id, profile_id, subscriptionswo iddie eindeutige Kennung ist, profile_idLinks zum Fremdkörper ideiner ProfileTabelle usw.

Oder gibt es Szenarien, in denen Sie ein solches Feld nicht hinzufügen möchten?

AJJ
quelle
61
Schauen Sie sich das deutsche Panzerproblem an, um ein Beispiel zu finden, bei dem eine einfache automatische Inkrementierungskennung ein Problem darstellt. Dies ist natürlich nur von Bedeutung, wenn Sie Ihre Ausweise in der Öffentlichkeit verwenden.
Bergi
24
@ArukaJ Der Punkt ist, dass es einige Informationen über das System verliert. Angenommen, die Datenbank enthält benutzerdefinierte Posts, von denen jeder eine sequenzielle ID erhält. Angenommen, Sie erstellen vier Posts, von denen jeder eine ID erhält: um 4 Uhr (20), 5 Uhr (25), 20 Uhr (100) und 21 Uhr (200). Anhand der IDs können Sie erkennen, dass zwischen 4 und 5 Uhr nur 5 Posts hinzugefügt wurden, während zwischen 20 und 21 Uhr 100 Posts hinzugefügt wurden. Wenn Sie versuchen, die Zeit für einen Denial-of-Service-Angriff zu ermitteln, könnte dies eine wertvolle Information sein.
Joshua Taylor
29
An alle, die sich über das "deutsche Panzerproblem" beschweren ... Wenn das einzige, was jemanden davon abhält, auf Daten zuzugreifen, ein Schlüssel in Ihrer URL ist, haben Sie größere Probleme als GUID gegenüber Auto INT.
Matthew Whited
11
@MatthewWhited Es geht nicht nur darum, Parameter in einer URL auszutauschen. Angenommen, Sie verwenden eine Site und erstellen gleichzeitig Asset 100 tund Asset 120 t + 60. Wenn Sie beide IDs (100 und 120) in unverschlüsselter Form sehen können, kennen Sie jetzt die Gesamtzahl der vorhandenen Assets sowie in etwa die Rate, mit der sie erstellt wurden. Dies ist ein Informationsleck. Dies ist nicht rein hypothetisch.
Chris Hayes
15
"Ist es eine gute Übung, immer ..."
brian_o

Antworten:

137

Es ist nie eine schlechte Idee, einen garantierten eindeutigen Zeilenbezeichner zu haben. Ich denke, ich sollte nicht nie sagen - aber lassen Sie uns mit der überwiegenden Mehrheit der Zeit gehen, es ist eine gute Idee.

Zu den theoretisch möglichen Nachteilen gehören ein zusätzlicher Index für die Wartung und der zusätzliche verwendete Speicherplatz. Das war für mich noch nie Grund genug, keinen zu benutzen.

GroßmeisterB
quelle
11
Das ist, was ich tue. Die meisten Leute benutzen entweder 'id' oder 'tablename_id' (wie user_id). Das Argument wird normalerweise nicht verwendet, wenn die Spalte benötigt wird, sondern wie sie benannt werden soll.
GroßmeisterB
103
Persönlich denke ich, dass der Tabellenname den Rest implizieren sollte. TableName.idim gegensatz zu TableName.TableName_id, denn worauf idbezieht sich das sonst noch ? Wenn ich ein anderes ID-Feld in der Tabelle habe, werde ich ihm einen Tabellennamen voranstellen, wenn es sich auf eine andere Tabelle bezieht
AJJ
10
@ArukaJ Sie haben erwähnt, dass Sie SQLite verwenden. Das ist eigentlich ein Sonderfall, da so eine Säule immer "unter der Haube" ist. Sie brauchen also nicht einmal zusätzlichen Platz, weil Sie einen bekommen, ob Sie wollen oder nicht. Die Zeilen-ID von SQLite ist immer eine 64-Bit-Ganzzahl. Wenn ich das richtig verstehe und Sie eine automatisch inkrementierende Zeile definieren, ist dies ein Alias ​​für die interne Zeilen-ID. Also könnte man es wohl immer machen! Siehe sqlite.org/autoinc.html
GrandmasterB
9
Die einzige Ausnahme, an die ich denken kann, ist, wenn Sie eine eindeutige Kennung haben, die auf andere Weise generiert wird. In diesem Fall sollte dies der Primärschlüssel sein und eine automatisch inkrementierende Kennung ist redundant.
HamHamJ
4
@GrandmasterB: Die aktuelle Version von SQLite ermöglicht das Erstellen von WITHOUT ROWIDTabellen (mit einem expliziten PRIMARY KEY) als Optimierung. Ansonsten ist eine INTEGER PRIMARY KEYSpalte ein Alias ​​für die Zeilen-ID.
Dan04
92

Ich bin mit allen Antworten vorher nicht einverstanden. Es gibt viele Gründe, warum es eine schlechte Idee ist, in allen Tabellen ein Auto-Inkrement-Feld hinzuzufügen.

Wenn Sie eine Tabelle haben, in der es keine offensichtlichen Schlüssel gibt, ist ein Auto-Inkrement-Feld eine gute Idee. Immerhin willst du nicht select * from blog where body = '[10000 character string]'. Du willst lieber select * from blog where id = 42. Ich würde argumentieren, dass Sie in den meisten Fällen wirklich eine eindeutige Kennung wünschen. keine fortlaufende eindeutige Kennung. Möglicherweise möchten Sie stattdessen einen universell eindeutigen Bezeichner verwenden.

In den meisten Datenbanken gibt es Funktionen zum Generieren zufälliger eindeutiger Bezeichner ( uuidin mysql, postgres. newidIn mssql). Mit diesen können Sie jederzeit Daten in mehreren Datenbanken auf verschiedenen Computern generieren, ohne dass eine Netzwerkverbindung besteht, und trotzdem Daten ohne Konflikte zusammenführen. Auf diese Weise können Sie mehrere Server und sogar Rechenzentren einfacher einrichten, z. B. mit Microservices.

Dadurch wird auch vermieden, dass Angreifer URLs zu Seiten erraten, auf die sie keinen Zugriff haben sollten. Wenn es eine https://example.com/user/1263gibt, gibt es wahrscheinlich auch eine https://example.com/user/1262. Dies könnte die Automatisierung eines Sicherheits-Exploits auf der Benutzerprofilseite ermöglichen.

Es gibt auch viele Fälle, in denen eine uuid-Spalte unbrauchbar oder sogar schädlich ist. Nehmen wir an, Sie haben ein soziales Netzwerk. Es gibt einen usersTisch und einen friendsTisch. Die Freundes-Tabelle enthält zwei Benutzer-ID-Spalten und ein Auto-Inkrement-Feld. Sie möchten 3mit befreundet sein 5, so dass Sie 3,5in die Datenbank einfügen . Die Datenbank fügt eine Auto-Inkrement-ID hinzu und speichert diese 1,3,5. Irgendwie 3klickt der Benutzer erneut auf den "Freund hinzufügen" -Button. Wenn Sie erneut 3,5in die Datenbank einfügen , fügt die Datenbank eine Auto-Inkrement-ID hinzu und fügt sie ein 2,3,5. Aber jetzt 3und 5sind zweimal miteinander befreundet! Das ist Platzverschwendung, und wenn Sie darüber nachdenken, ist dies auch die Spalte für die automatische Inkrementierung. Alles was Sie brauchen, um zu sehen, ob aundbare friends ist für die Zeile mit diesen beiden Werten auszuwählen. Sie sind zusammen eine eindeutige Zeilenkennung. (Sie wollen wahrscheinlich eine gewisse Logik zu tun , schreiben , um sicherzustellen , 3,5und 5,3werden dedupliziert.)

Es gibt immer noch Fälle, in denen sequentielle IDs nützlich sein können, wie beim Erstellen eines URL-Kürzers, aber meistens (und sogar mit dem URL-Kürzer) möchten Sie stattdessen eine zufällig generierte eindeutige ID verwenden.

TL; DR: Verwenden Sie UUIDs anstelle der automatischen Inkrementierung, wenn Sie nicht bereits eine eindeutige Methode zur Identifizierung jeder Zeile haben.

Filip Haglund
quelle
26
Das Problem mit UUIDs besteht darin, dass sie für die meisten Tabellen zu viel Platz beanspruchen. Verwenden Sie für jede Tabelle den richtigen eindeutigen Bezeichner.
Stephen
49
Der gesamte Absatz über die Eindeutigkeit ist umstritten - die Eindeutigkeit kann mit oder ohne Primärschlüssel erzwungen werden. Außerdem sind UUIDs theoretisch gesehen besser, aber schrecklich zu verwenden, wenn Sie DBA-Aufgaben debuggen / ausführen oder auf andere Weise etwas tun, das sich nicht "Angriffen widersetzt".
11
Ein weiteres Szenario, in dem UUIDs besser geeignet sind: Implementieren einer idempotenten PUT-Operation, damit Sie Anforderungen sicher wiederholen können, ohne doppelte Zeilen einzuführen.
Yurez
21
Wenn Sie eine eindeutige ID haben (fortlaufend oder auf andere Weise), bedeutet dies nicht, dass Sie diese ID Benutzern der Anwendung zur Verfügung stellen.
Dave Sherohman
7
Rein aus Datenbanksicht ist diese Antwort völlig falsch. Durch die Verwendung von UUIDs anstelle des automatischen Inkrementierens von Ganzzahlen werden die Indizes viel zu schnell vergrößert, und die Leistung und der Speicherverbrauch werden nachteilig beeinflusst. Wenn Sie aus der Sicht eines Webdienstes oder einer Web-App sprechen, sollte sich ohnehin eine Schicht zwischen der Datenbank und dem Front-End befinden. Alles andere ist schlechtes Design. Die Verwendung von Daten als Primärschlüssel ist noch schlimmer. Primärschlüssel sollten nur auf der Datenschicht verwendet werden, nirgendwo anders.
Betrunkener Code-Affe
60

Autoincemental-Schlüssel haben meistens Vorteile.

Einige mögliche Nachteile könnten jedoch sein:

  • Wenn Sie einen Geschäftsschlüssel haben, müssen Sie auch einen eindeutigen Index für diese Spalte (n) hinzufügen, um Geschäftsregeln durchzusetzen.
  • Wenn Sie Daten zwischen zwei Datenbanken übertragen, insbesondere wenn sich die Daten in mehr als einer Tabelle befinden (dh Master / Detail), ist dies nicht einfach, da Sequenzen nicht zwischen Datenbanken synchronisiert werden und Sie zuerst eine Äquivalenztabelle mit erstellen müssen Geschäftsschlüssel, um herauszufinden, welche ID aus der Ursprungsdatenbank mit welcher ID in der Zieldatenbank übereinstimmt. Dies sollte jedoch beim Übertragen von Daten von / zu isolierten Tabellen kein Problem sein.
  • Viele Unternehmen verfügen über Ad-hoc-, Grafik-, Point-and-Click- und Drag-and-Drop-Reporting-Tools. Da autoinkrementelle IDs bedeutungslos sind, wird es für diese Art von Benutzern schwierig sein, die Daten außerhalb der "App" zu verstehen.
  • Wenn Sie den Geschäftsschlüssel versehentlich ändern, wird diese Zeile wahrscheinlich nie wiederhergestellt, da Sie für den Menschen keine Möglichkeit mehr haben, sie zu identifizieren. Das hat einmal einen Fehler in der BitCoin-Plattform verursacht .
  • Einige Designer fügen einer Verknüpfungstabelle zwischen zwei Tabellen eine ID hinzu, wenn die PK einfach aus den beiden Fremd-IDs bestehen soll. Wenn sich die Join-Tabelle zwischen drei oder mehr Tabellen befindet, ist eine autoinkrementelle ID zwar sinnvoll, Sie müssen jedoch einen eindeutigen Schlüssel hinzufügen, wenn diese für die Kombination von FKs zum Erzwingen von Geschäftsregeln gilt.

Hier ist ein Wikipedia-Artikel über die Nachteile von Ersatzschlüsseln.

Tulains Córdova
quelle
13
Die Schuld an dem mt.gox-Fehler bei Ersatzschlüsseln scheint eher zweifelhaft. Das Problem war, dass sie alle Felder in ihren zusammengesetzten Schlüssel eingeschlossen haben, sogar veränderbare / formbare Felder.
CodesInChaos
6
Ein "sozialer" Nachteil der Verwendung von Auto-Inkrement-Schlüsseln besteht darin, dass "das Unternehmen" manchmal davon ausgeht, dass es niemals Lücken geben darf, und nachfragt, was mit den fehlenden Zeilen geschehen ist, die beim Auftreten eines fehlgeschlagenen Einfügens aufgetreten sind (Transaktions-Rollback).
Rick Ryker
4
Ein weiterer Nachteil ist, dass wenn das System so groß wird, dass Sie die Datenbank sichern müssen, Sie Autoincrement nicht mehr verwenden können, um einen global eindeutigen Schlüssel zu erstellen. Wenn Sie an diesen Punkt gelangen, haben Sie möglicherweise viel Code, der auf dieser Annahme beruht. Es gibt andere Möglichkeiten, einen eindeutigen Bezeichner zu erstellen, der bei einem Shard der Datenbank weiterhin funktioniert.
Kasperd
1
@Voo Es kann nicht garantiert werden, dass Ihre gewählte Datenbank dies unterstützt. Wenn Sie versuchen, eine höhere Ebene als die Datenbank selbst zu implementieren, verlieren Sie einige der Garantien, die SQL Ihnen geben würde. Schließlich erhöht jede zentralisierte Zuweisung von IDs die Latenz, wenn Sie ein verteiltes System haben.
Kasperd
1
@Voo Natürlich sollte man unabhängig von der Größe des Systems nicht zu viele Annahmen über die Art der automatisch inkrementierten IDs treffen. Wenn Sie nur eine einzige Datenbank haben, werden sie der Reihe nach zugewiesen, es gibt jedoch keine Garantie dafür, dass sie der Reihe nach festgeschrieben sind. Und es kann eine Lücke in der Sequenz geben, da nicht alle Transaktionen festgeschrieben werden.
Kasperd
20

Nein, Sie müssen NICHT immer einen numerischen AutoInc-PK haben.

Wenn Sie Ihre Daten sorgfältig analysieren, identifizieren Sie häufig natürliche Schlüssel in den Daten. Dies ist häufig der Fall, wenn die Daten für das Unternehmen eine intrinsische Bedeutung haben. Manchmal sind die PKs Artefakte aus alten Systemen, die die Geschäftsbenutzer als zweite Sprache verwenden, um Attribute ihres Systems zu beschreiben. Ich habe Fahrzeug-VIN-Nummern gesehen, die beispielsweise als Primärschlüssel einer "Fahrzeug" -Tabelle in einem Flottenmanagementsystem verwendet werden.

Wenn Sie jedoch bereits eine eindeutige Kennung haben, verwenden Sie diese. Erstellen Sie keinen zweiten, bedeutungslosen Primärschlüssel. Es ist verschwenderisch und kann Fehler verursachen.

Manchmal können Sie eine AutoInc-PK verwenden, um einen für den Kunden aussagekräftigen Wert zu generieren, z. B. Richtliniennummern. Setzen Sie den Startwert auf einen sinnvollen Wert und wenden Sie Geschäftsregeln für führende Nullen usw. an. Dies ist wahrscheinlich ein Ansatz, der das Beste aus zwei Welten ist.

Wenn Sie eine geringe Anzahl von Werten haben, die relativ statisch sind, verwenden Sie Werte, die für den Systembenutzer sinnvoll sind. Warum sollten Sie 1,2,3 verwenden, wenn Sie L, C, H verwenden könnten, wobei L, H und C für Leben, Auto und Privat in einem Versicherungskontext vom Typ "Versicherungsvertrag" stehen, oder, um auf das VIN-Beispiel zurückzukommen, wie wäre es mit "TO"? "für Toyota? Alle Toyata-Fahrzeuge haben eine Fahrgestellnummer, die mit "TO" beginnt. Dies ist eine Sache, an die sich die Benutzer weniger erinnern müssen, und die die Wahrscheinlichkeit verringert, dass sie Programmier- und Benutzerfehler einführen. Sie können sogar als Ersatz für eine vollständige Beschreibung in Managementberichten verwendet werden, um die Berichte zu vereinfachen zu schreiben und vielleicht schneller zu generieren.

Eine Weiterentwicklung davon ist wahrscheinlich "eine Brücke zu weit", und ich empfehle es im Allgemeinen nicht, aber ich beziehe es der Vollständigkeit halber ein, und Sie finden möglicherweise eine gute Verwendung dafür. Verwenden Sie also die Beschreibung als Primärschlüssel. Für sich schnell ändernde Daten ist dies ein Gräuel. Für sehr statische Daten, die bei All The Time gemeldet werden , ist dies möglicherweise nicht der Fall. Ich erwähne es nur, damit es dort als eine Möglichkeit sitzt.

Ich benutze zwar AutoInc-PKs, aber ich beschäftige mich nur mit meinem Gehirn und suche zuerst nach besseren Alternativen. Die Kunst des Datenbankdesigns macht etwas Sinnvolles, das schnell abgefragt werden kann. Zu viele Joins behindern dies.

BEARBEITEN Ein weiterer wichtiger Fall, in dem Sie keine automatisch generierte PK benötigen, sind Tabellen, die die Schnittmenge zweier anderer Tabellen darstellen. Um bei der Auto-Analogie zu bleiben, hat ein Auto 0..n Zubehörteile. Jedes Zubehörteil ist bei vielen Autos vorhanden. Um dies darzustellen, erstellen Sie eine Car_Accessory-Tabelle, die die PKs von Car and Accessory und andere relevante Informationen über den Link Dates etc. enthält.

Was Sie (normalerweise) nicht benötigen, ist ein AutoInc PK auf diesem Tisch - auf diesen kann nur über das Auto zugegriffen werden.

mcottle
quelle
4
> Alle Toyata-Autos haben eine Fahrgestellnummer, die mit "TO" beginnt. Das stimmt einfach nicht. Sie beginnen mit "JT", wenn sie in Japan hergestellt werden. In den USA gebaute Toyotas haben völlig unterschiedliche VINs. De.wikibooks.org/wiki/…
Monty Harder
17
Don't create a second, meaningless primary key; it's wasteful and may cause errors.Wenn die Art und Weise, wie Sie die Eindeutigkeit eines Datensatzes herstellen, aus einer Kombination von 6 Spalten besteht, ist die ständige Verknüpfung aller 6 Spalten sehr fehleranfällig. Die Daten haben natürlich eine PK, aber es ist besser, eine idSpalte und eine eindeutige Einschränkung für diese 6 Spalten zu verwenden.
Brad
14
Ich gebe zu, einige dieser Vorschläge gehen mir etwas weit. Ja, pragmatisch zu sein ist in Ordnung, aber ich kann nicht zählen, wie oft jemand das Leben seines Erstgeborenen geschworen hat, dass ein Attribut aus dem Bereich für den Rest der Tage einzigartig bleibt. Normalerweise hat das bis zur zweiten Woche nach dem Start gut funktioniert, als die ersten Duplikate aufgetaucht sind. ;) Eine "Beschreibung" als PK zu verwenden, ist einfach weit hergeholt.
AnoE
2
@Monty, du hast recht. Fehlbares Gedächtnis, es ist 20 Jahre her, dass ich die Flottenmanagementsysteme entwickelt habe. Nein, die VIN war nicht der Primärschlüssel :) Ich habe eine AutoInc Asset_ID IIRC verwendet, die zu etwas führt, das ich vergessen habe. Tabellen, die die Verknüpfungen für viele-zu-viele-Beziehungen darstellen, in denen Sie beispielsweise Auto mit Zubehör verknüpfen (z. B. Schiebedach). Viele Autos verfügen über viele Zubehörteile. Daher benötigen Sie eine "Car_Accessory" -Tabelle, die Car_ID und Accessory_ID enthält, jedoch auf keinen Fall Car_Accesory_ID als eine AutoInc PK.
mcottle
7
Es ist wirklich erstaunlich, wie wenige WIRKLICH unveränderliche "natürliche Schlüssel" es gibt. SSN's? Nein, sie können sich ändern. Es ist selten, aber es kann passieren. Benutzernamen? Nee. Irgendwann wird jemand einen gültigen Geschäftsgrund haben, sich zu ändern. VIN ist oft ein Lehrbuchbeispiel, aber es gibt nicht viele andere. Sogar Privatadressen können sich ändern, wenn sich die Straßennamen ändern.
Erik Funkenbusch
12

Viele Tabellen haben bereits eine natürliche eindeutige ID. Fügen Sie diesen Tabellen keine weitere eindeutige ID-Spalte (automatische Inkrementierung oder auf andere Weise) hinzu. Verwenden Sie stattdessen die natürliche eindeutige ID. Wenn Sie eine weitere eindeutige ID hinzufügen, haben Sie im Wesentlichen eine Redundanz (Duplizierung oder Abhängigkeit) in Ihren Daten. Dies widerspricht den Grundsätzen der Normalisierung. Eine eindeutige ID ist für die Genauigkeit von der anderen abhängig. Das bedeutet , dass sie sich perfekt an synchron gehalten werden müssen jederzeit in jedem System , das diese Zeilen verwaltet. Es ist nur eine weitere Schwachstelle in Ihrer Datenintegrität, die Sie nicht wirklich langfristig verwalten und validieren müssen möchten.

Die meisten Tabellen benötigen heutzutage nicht wirklich die sehr geringe Leistungssteigerung, die eine zusätzliche eindeutige ID-Spalte bieten würde (und manchmal beeinträchtigt dies sogar die Leistung). Vermeiden Sie Redundanzen wie die Pest! Widersetze dich überall dort, wo es dir vorgeschlagen wird. Es ist Anathema. Und beachten Sie das Zitat. Alles sollte so einfach wie möglich sein, aber nicht einfacher. Haben Sie keine zwei eindeutigen IDs, bei denen eine ausreicht, auch wenn die natürliche weniger aufgeräumt zu sein scheint.

Brad Thomas
quelle
3
Sollten Sie "natürliche" IDs nicht nur als Primärschlüssel verwenden, wenn sie sich garantiert nie ändern? Zum Beispiel sollten Sie keine Führerscheinnummer als Primärschlüssel verwenden, da Sie, wenn eine Person einen neuen Führerschein erhält, nicht nur diese Tabelle aktualisieren müssen, sondern auch Tabellen mit Fremdschlüsseln, die darauf verweisen!
Ekolis
1
Es gibt mehrere Gründe, warum die Führerscheinnummer nicht als natürliche eindeutige ID eingestuft wird. Erstens werden einige von ihnen von anderen Daten wie Geburtsdatum und Name abgeleitet. Sie sind nicht garantiert in allen Staaten einzigartig. Und um Ihr Beispiel zu nehmen: Wenn einer Person eine Lizenz mit derselben Nummer, aber möglicherweise einem verlängerten Ablauf, erneut ausgestellt wird, was passiert dann? Sie haben eine andere Lizenz mit der gleichen Nummer. Eine natürliche ID muss noch die grundlegenden Eigenschaften eines Primärschlüssels erfüllen. Die Führerscheinnummer (zumindest in den USA) weist diesbezüglich einige Mängel auf.
Brad Thomas
1
OK, ich glaube, ich habe damals die Definition der natürlichen Identität falsch verstanden. Ich dachte, es sei nur eine ID, die durch die Geschäftsregeln definiert ist, unabhängig davon, ob sie tatsächlich unveränderlich ist oder nicht.
Ekolis
10

Bei größeren Systemen ist ID ein Konsistenzverbesserer. Verwenden Sie es fast überall. In diesem Zusammenhang werden einzelne Primärschlüssel NICHT empfohlen, sie sind im Endeffekt teuer (lesen Sie, warum).

Jede Regel hat eine Ausnahme. Daher benötigen Sie möglicherweise keine automatische Inkrementierungs-ID für Ganzzahlen für Staging-Tabellen, die für den Export / Import verwendet werden, sowie für ähnliche Einweg- oder temporäre Tabellen. Sie würden auch GUIDs anstelle von IDs auf verteilten Systemen bevorzugen.

Viele Antworten hier deuten darauf hin, dass ein vorhandener eindeutiger Schlüssel verwendet werden sollte. Na auch wenn es 150 Zeichen hat? Ich glaube nicht

Nun mein Hauptpunkt:

Es sieht so aus, als würden Gegner von autoincrement integer ID von kleinen Datenbanken mit bis zu 20 Tabellen sprechen. Dort können sie sich einen individuellen Zugang zu jedem Tisch leisten.

ABER wenn Sie ein ERP mit mehr als 400 Tabellen haben, ist es einfach sehr sinnvoll, überall (mit Ausnahme der oben genannten Fälle) eine ganzzahlige Autoincrement-ID zu haben . Sie verlassen sich nicht auf andere eindeutige Felder, auch wenn diese vorhanden und für die Eindeutigkeit gesichert sind.

  • Sie profitieren von einer universellen, zeitsparenden, zeitsparenden und leicht zu merkenden Konvention.
  • In den meisten Fällen müssen Sie JOINTabellen, ohne zu überprüfen, was die Schlüssel sind.
  • Sie können universelle Coderoutinen verwenden, die mit Ihrer Spalte für das automatische Inkrementieren von Ganzzahlen arbeiten.
  • Sie können Ihr System mit neuen Tabellen oder Benutzer-Plugins erweitern, die vorher nicht vorgesehen waren, indem Sie einfach auf die IDs vorhandener Tabellen verweisen. Sie sind bereits von Anfang an da, ohne zusätzliche Kosten.

Auf größeren Systemen kann es sich lohnen, die geringfügigen Vorteile dieser einzelnen Primärschlüssel zu ignorieren und in den meisten Fällen die ganzzahlige Autoincrement-ID zu verwenden. Durch die Verwendung vorhandener eindeutiger Felder als Primärschlüssel werden möglicherweise einige Bytes pro Datensatz gespart, aber zusätzliche Speicher- oder Indizierungszeiten sind in den heutigen Datenbankmodulen kein Problem . Tatsächlich verlieren Sie viel mehr Geld und Ressourcen durch verschwendete Zeit der Entwickler / Betreuer. Die heutige Software sollte für den Zeit- und Arbeitsaufwand von Programmierern optimiert werden - welcher Ansatz mit konsistenten IDs besser erfüllt wird.

Miroxlav
quelle
Aus persönlicher Erfahrung stimme ich der zweiten Hälfte Ihrer Antwort voll und ganz zu. Sie benötigen viel seltener global eindeutige Schlüssel als schnelle und kompakte Indizes. Wenn Sie eine benötigen, erstellen Sie eine GlobalEntities-Tabelle mit einer automatisch generierten ID und einer UUID-Spalte. Fügen Sie dann der Customers-Tabelle beispielsweise einen ExGlobalEntityId-Fremdschlüssel hinzu. Oder verwenden Sie einen Hash einiger Werte.
Betrunkener Code-Affe
8

Es ist keine gute Praxis, überflüssige Designs zu verwenden. Dh, es ist nicht ratsam, immer einen Auto-Inkrement-Int-Primärschlüssel zu haben, wenn einer nicht benötigt wird.

Schauen wir uns ein Beispiel an, bei dem eines nicht benötigt wird.

Sie haben eine Tabelle für Artikel - diese hat einen int-Primärschlüssel idund eine varchar-Spalte mit dem Namen title.

Sie haben auch eine Tabelle mit Artikelkategorien - idint Primärschlüssel, varchar name.

Eine Zeile in der Artikeltabelle hat eine id5 und eine title "Wie man Gans mit Butter kocht". Sie möchten diesen Artikel mit den folgenden Zeilen in Ihrer Kategorietabelle verknüpfen: "Geflügel" ( ID : 20), "Gans" ( ID : 12), "Kochen" ( ID : 2), "Butter" (ID: 9) .

Jetzt haben Sie 2 Tabellen: Artikel und Kategorien. Wie stellen Sie die Beziehung zwischen den beiden her?

Sie könnten eine Tabelle mit 3 Spalten haben: id (Primärschlüssel), article_id (Fremdschlüssel), category_id (Fremdschlüssel). Aber jetzt haben Sie etwas wie:

| id | a_id | c_id |
| 1 | 5 | 20 |
| 2 | 5 | 12 |
| 3 | 5 | 2 |

Eine bessere Lösung besteht darin, einen Primärschlüssel zu haben, der aus 2 Spalten besteht.

| a_id | c_id |
| 5 | 20 |
| 5 | 12 |
| 5 | 2 |

Dies kann folgendermaßen erreicht werden:

create table articles_categories (
  article_id bigint,
  category_id bigint,
  primary key (article_id, category_id)
) engine=InnoDB;

Ein weiterer Grund, keine Ganzzahl mit automatischer Inkrementierung zu verwenden, besteht darin, dass Sie UUIDs für Ihren Primärschlüssel verwenden.

UUIDs sind ihrer Definition nach eindeutig, was dasselbe bewirkt wie die Verwendung eindeutiger Ganzzahlen. Sie haben auch ihre eigenen zusätzlichen Vorteile (und Nachteile) gegenüber ganzen Zahlen. Mit einer UUID wissen Sie beispielsweise, dass die eindeutige Zeichenfolge, auf die Sie sich beziehen, auf einen bestimmten Datensatz verweist. Dies ist nützlich, wenn Sie nicht über eine zentrale Datenbank verfügen oder wenn Anwendungen die Möglichkeit haben, Datensätze offline zu erstellen (und sie zu einem späteren Zeitpunkt in die Datenbank hochzuladen).

Am Ende müssen Sie nicht über Primärschlüssel nachdenken. Sie müssen sich diese als die Funktion vorstellen, die sie ausführen. Warum brauchen Sie Primärschlüssel? Um bestimmte Datensätze aus einer Tabelle anhand eines Feldes eindeutig identifizieren zu können, das in Zukunft nicht mehr geändert wird. Benötigen Sie dazu eine bestimmte Spalte idoder können Sie diese eindeutige Identifikation auf andere (unveränderliche) Daten stützen?

anw
quelle
7

Oder gibt es Szenarien, in denen Sie ein solches Feld nicht hinzufügen möchten?

Sicher.

Erstens gibt es Datenbanken, die keine automatischen Zuwächse aufweisen (z. B. Oracle, das mit Sicherheit nicht zu den kleinsten Konkurrenten zählt). Dies sollte ein erster Hinweis darauf sein, dass nicht jeder sie mag oder braucht.

Noch wichtiger ist, überlegen Sie, wie die ID tatsächlich lautet - sie ist ein Primärschlüssel für Ihre Daten. Wenn Sie eine Tabelle mit einem anderen Primärschlüssel haben, benötigen Sie keine ID und sollten auch keine haben. Beispielsweise hat eine Tabelle (EMPLOYEE_ID, TEAM_ID)(in der sich jeder Mitarbeiter gleichzeitig in mehreren Teams befinden kann) einen klar definierten Primärschlüssel, der aus diesen beiden IDs besteht. Das Hinzufügen einer Autoincrement- IDSpalte, die auch ein Primärschlüssel für diese Tabelle ist, macht überhaupt keinen Sinn. Jetzt schleppen Sie 2 Primärschlüssel herum und das erste Wort in "Primärschlüssel" sollte Ihnen einen Hinweis geben, dass Sie wirklich nur einen haben sollten.

AnoE
quelle
9
(Kein Oracle-Benutzer, aber verzeihen Sie die Frage.) Verwendet Oracle Sequence nicht auf die gleiche Weise wie andere Benutzer Autoincrement / Identity? Ist zu sagen, dass Oracle keinen Autoincrement-Datentyp hat, wirklich nur ein sematisches Argument?
Brad
Nun, das war nur ein kleiner Punkt. Der Hauptteil ist, dass eine laufende ID nicht für jede Tabelle geeignet ist. Daher ist es möglicherweise nicht die klügste Methode, eine Auto-ID auf jede einzelne Tabelle zu legen.
AnoE
Es gibt keine zwei Primärschlüssel, es gibt nur einen Primärschlüssel und alle anderen werden als Kandidatenschlüssel bezeichnet, wenn sie auch als Primärschlüssel dienen können.
rahul tyagi
7

Normalerweise verwende ich eine "Identität" -Spalte (automatisch inkremenntierende Ganzzahl), wenn ich neue Tabellen für "langlebige" Daten definiere (Datensätze, die ich voraussichtlich einmal einfügen und unbegrenzt aufbewahren werde, auch wenn sie durch Setzen eines Bitfelds "logisch gelöscht" werden ).

Es gibt einige Situationen, an die ich denken kann, wenn Sie sie nicht verwenden möchten. Die meisten ergeben sich aus Szenarien, in denen eine Tabelle in einer Instanz der Datenbank nicht die maßgebliche Quelle für neue ID-Werte sein kann:

  • Bei inkrementellen IDs handelt es sich um zu viele Informationen für einen potenziellen Angreifer. Die Verwendung einer Identitätsspalte für "öffentlich zugängliche" Datendienste macht Sie anfällig für das "deutsche Panzerproblem". Wenn die Datensatz-ID 10234 vorhanden ist, ist es naheliegend, dass die Datensätze 10233, 10232 usw. vorhanden sind, und zwar mindestens bis zum Datensatz 10001, und dann können Sie leicht nach den Datensätzen 1001, 101 und 1 suchen, um herauszufinden, wo Ihre Identitätsspalte begonnen hat. V4-GUIDs, die hauptsächlich aus zufälligen Daten bestehen, unterbrechen dieses inkrementelle Verhalten von Entwurf, sodass eine GUID, die durch Inkrementieren oder Dekrementieren eines Bytes der GUID erstellt wird, nicht unbedingt vorhanden ist, sodass es für einen Angreifer schwieriger ist, einen bestimmten Dienst zu verwenden für Single-Record-Retrieval als Dump-Tool. Es gibt andere Sicherheitsmaßnahmen, die den Zugriff besser einschränken können, dies hilft jedoch.
  • In M: M Querverweistabellen. Das ist eine Art Gimme, aber ich habe es schon mal gesehen. Wenn Sie eine Viele-zu-Viele-Beziehung zwischen zwei Tabellen in Ihrer Datenbank haben, ist die Go-To-Lösung eine Querverweistabelle, die Fremdschlüsselspalten enthält, die auf die PK jeder Tabelle verweisen. Die PK dieser Tabelle sollte praktisch immer ein zusammengesetzter Schlüssel der beiden Fremdschlüssel sein, um das integrierte Indexverhalten zu erhalten und die Eindeutigkeit der Referenzen sicherzustellen.
  • Wenn Sie vorhaben, eine Menge in dieser Tabelle einzufügen und zu löschen. Der wahrscheinlich größte Nachteil von Identitätsspalten ist der zusätzliche Hoopla, den Sie durchlaufen müssen, wenn Sie Zeilen aus einer anderen Tabelle oder Abfrage einfügen, in der Sie die Schlüsselwerte der Originaltabelle beibehalten möchten. Sie müssen "Identity Insert" aktivieren (wie auch immer dies in Ihrem DBMS geschehen ist), dann manuell sicherstellen, dass die von Ihnen eingegebenen Schlüssel eindeutig sind, und wenn Sie mit dem Import fertig sind, müssen Sie den Identitätszähler im festlegen Metadaten der Tabelle auf den maximal vorhandenen Wert. Wenn diese Operation in dieser Tabelle häufig vorkommt, ziehen Sie ein anderes PK-Schema in Betracht.
  • Für verteilte Tabellen.Identitätsspalten eignen sich hervorragend für Einzelinstanzdatenbanken, Failover-Paare und andere Szenarien, in denen jeweils eine Datenbankinstanz die alleinige Berechtigung für das gesamte Datenschema hat. Es ist jedoch nur so groß, dass ein Computer schnell genug ist. Durch Replikation oder Versand von Transaktionsprotokollen können Sie zusätzliche schreibgeschützte Kopien erhalten. Die Größe dieser Lösung ist jedoch ebenfalls begrenzt. Früher oder später müssen zwei oder mehr Serverinstanzen Daten einfügen und dann miteinander synchronisieren. In diesem Fall sollten Sie ein GUID-Feld anstelle eines inkrementellen Felds verwenden, da die meisten DBMS vorkonfiguriert sind, einen Teil der von ihnen als instanzspezifische Kennung generierten GUIDs zu verwenden, und den Rest der Kennung dann nach dem Zufallsprinzip generieren oder inkrementell. In beiden Fällen,
  • Wenn Sie die Eindeutigkeit für mehrere Tabellen in der Datenbank erzwingen müssen.In Buchhaltungssystemen ist es beispielsweise üblich, das Hauptbuch (mit einer Zeile für jede Gutschrift oder Belastung jedes Kontos, das jemals stattgefunden hat, so dass es sehr schnell sehr groß wird) als eine Folge von Tabellen zu verwalten, die jeweils einen Kalendermonat darstellen / Jahr. Anschließend können Ansichten erstellt werden, um sie für die Berichterstellung zu verknüpfen. Logischerweise ist dies alles ein sehr großer Tisch, aber das Zerlegen erleichtert die Wartungsarbeiten der DB. Es stellt sich jedoch das Problem, wie Einfügungen in mehrere Tabellen verwaltet werden können (sodass Sie im nächsten Monat beginnen können, Transaktionen zu protokollieren, während der letzte noch geschlossen wird), ohne dass doppelte Schlüssel entstehen. Auch hier sind GUIDs anstelle von Identity Integer-Spalten die Lösung, da das DBMS darauf ausgelegt ist, diese auf wirklich einzigartige Weise zu generieren.

Wie ich hoffentlich erwähnt habe, gibt es Problemumgehungen, die die Verwendung von Identitätsspalten in diesen Situationen ermöglichen. In den meisten Fällen ist das Upgrade von der ganzzahligen Identitätsspalte auf eine GUID jedoch einfacher und löst das Problem vollständiger.

KeithS
quelle
1
Es gibt Fälle, in denen Sie die ID in M: N-Tabellen (mithilfe von Spalten ID, ID_M, ID_N) weiterhin benötigen können, weil Sie Eigenschaften an Instanzen Ihrer M: N-Beziehung anhängen.
Miroxlav
V4 GUIDS verwenden garantiert kein kryptografisch starkes PNRG, daher sollten Sie sich bei Ihrem ersten Beispiel imo nicht darauf verlassen (auch wenn Ihre Datenbank-Engine stärkere Versprechungen macht, ist dies möglicherweise in Ordnung, aber nicht portabel). Ansonsten ein gut durchdachter Beitrag.
Voo
1
@miroxlav - Ich würde behaupten, wenn eine Tabelle über genügend zusätzliche Metadaten bezüglich der Beziehung verfügt, dass eine separate PK außerhalb der beiden FKs eine gute Idee ist, handelt es sich nicht mehr wirklich um eine Querverweistabelle. es ist seine eigene Entität, die sich zufällig auf die beiden anderen bezieht.
KeithS
@Voo - Sie haben Recht, V4-GUIDs sind nicht garantiert kryptografisch zufällig, sondern nur eindeutig (wie alle GUIDs). Die Schwanzzahlen von US-Düsenjägern werden jedoch auch nicht aus kryptografisch zufälligen Saatgutdaten / -algorithmen generiert. Was Sie wirklich suchen, ist eine dünn besiedelte Domäne. Eine V4-GUID enthält 112 Byte zufällige Daten, mit denen 5e33-Datensätze eindeutig identifiziert werden können.
KeithS
Um diese Zahl ins rechte Licht zu rücken: Jeder Mann, jede Frau und jedes Kind auf dem Planeten (alle 7 Milliarden) könnte 741 Billionen einzeln katalogisierte und identifizierte Datenpunkte in unserer Datenbank haben, und wir würden immer noch nur einen verfügbaren GUID-Wert pro Milliarde verwenden . Big Data ist als globale Branche nicht einmal annähernd so umfangreich. Selbst wenn der GUID-Generierung ein Muster zugewiesen wurde, sind andere Entropiequellen beteiligt, beispielsweise die Reihenfolge, in der Daten in das System eingegeben werden und eine GUID zugewiesen wird.
KeithS
7

Ein automatisch inkrementierter (Identitäts-) Primärschlüssel ist eine gute Idee, mit der Ausnahme, dass er außerhalb des Kontexts der Datenbank und der unmittelbaren Clients dieser Datenbank bedeutungslos ist. Wenn Sie zum Beispiel einige Daten in eine andere Datenbank übertragen und dort speichern und dann unterschiedliche Daten in beide Datenbanktabellen schreiben, weichen die IDs voneinander ab, dh Daten mit der ID 42 in einer Datenbank stimmen nicht unbedingt mit den Daten überein mit einer ID von 42 in der anderen.

Wenn es dennoch erforderlich ist, Zeilen außerhalb der Datenbank eindeutig zu identifizieren (und dies ist häufig der Fall), müssen Sie für diesen Zweck einen anderen Schlüssel haben. Ein sorgfältig ausgewählter Geschäftsschlüssel reicht aus, Sie werden jedoch häufig eine große Anzahl von Spalten benötigen, um die Eindeutigkeit zu gewährleisten. Eine andere Methode besteht darin, eine ID-Spalte als automatisch inkrementierten geclusterten Primärschlüssel und eine andere eindeutige Kennung (GUID) als nicht geclusterten eindeutigen Schlüssel zu verwenden, um die Zeile eindeutig zu identifizieren, wo immer sie auf der Welt vorhanden ist. Der Grund, warum Sie in diesem Fall immer noch über einen automatisch inkrementierten Schlüssel verfügen, besteht darin, dass es effizienter ist, den automatisch inkrementierenden Schlüssel zu gruppieren und zu indizieren, als dies mit einer Guid zu tun.

Ein Fall, in dem Sie möglicherweise keinen automatisch inkrementierenden Schlüssel wünschen, ist eine Viele-zu-Viele-Tabelle, in der der Primärschlüssel eine Verbindung der ID-Spalten von zwei anderen Tabellen ist (Sie könnten hier immer noch einen automatisch inkrementierenden Schlüssel haben, aber ich verstehe den Sinn nicht).

Eine andere Frage ist der Datentyp des automatisch inkrementierten Schlüssels. Mit einem Int32 erhalten Sie einen großen, aber relativ begrenzten Wertebereich. Persönlich verwende ich häufig Bigint-Spalten für die ID, um praktisch nie befürchten zu müssen, dass die Werte ausgehen.

MatthewToday
quelle
6

Da andere den Fall eines inkrementierenden Primärschlüssels vertreten haben, werde ich einen für eine GUID erstellen:

  • Es ist garantiert einzigartig
  • Sie können für Daten in Ihrer Anwendung einen Trip weniger in die Datenbank durchführen. (Für eine Typentabelle können Sie zum Beispiel die GUID in der Anwendung speichern und diese zum Abrufen des Datensatzes verwenden. Wenn Sie eine Identität verwenden, müssen Sie die Datenbank nach Namen abfragen, und ich habe viele Anwendungen gesehen, die dies tun, um die PK zu erhalten und fragt es später erneut ab, um die vollständigen Details zu erhalten).
  • Dies ist nützlich, um Daten auszublenden. www.domain.com/Article/2 Lässt mich wissen, dass Sie nur zwei Artikel haben, während www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a mir nichts sagt.
  • Sie können Datensätze aus verschiedenen Datenbanken einfach zusammenführen.
  • MSFT verwendet GUIDS für die Identität.

Bearbeiten: Punkt duplizieren

Drei-Wert-Logik
quelle
5
-1. Eine GUID / UUID ist nicht garantiert eindeutig und nicht zu 100% eindeutig. Eine GUID ist immer noch eine endliche Länge, so dass Sie zu einem bestimmten Zeitpunkt das Risiko eingehen können, ein Duplikat zu erhalten, obwohl dies höchst unwahrscheinlich ist. Ihr Hinweis zu weniger Fahrten in die Datenbank ist ebenfalls ungültig. Warum können Sie die primäre ID nicht in der Anwendung speichern, wie Sie dies mit dem GUID-Schlüssel tun können?
Niklas H
2
Jeff Atwood sagt es viel besser als ich es jemals könnte. blog.codinghorror.com/primary-keys-ids-versus-guids
Three Value Logic
Warum können Sie die primäre ID nicht in Ihrer Anwendung speichern? Weil die Datenbank es erstellt. Wenn Sie Ihre Seeds in einer leeren Datenbank ausführen, können Sie davon ausgehen, dass die ID 1 lautet. Was ist, wenn Sie dasselbe Skript in einer Datenbank mit darin enthaltenen Daten ausführen? Die ID wird nicht 1 sein.
Three Value Logic
Sie haben nichts über das Erstellen von IDs in der Anwendung gesagt - Sie haben nur "Speichern" geschrieben. Wenn es jedoch erforderlich ist, die ID außerhalb der Datenbank zu erstellen, kann eine GUID die Antwort sein.
Niklas H
2
Ich würde hinzufügen, dass sie besser skalieren. Big Data NoSQL-Datenbanken wie Cassandra unterstützen nicht einmal automatische Inkrementierungsschlüssel.
Karl Bielefeldt
2

Grundsätzlich sollte jede Tabelle eine zuverlässige Methode haben, um eine Zeile eindeutig zu identifizieren. Ein Primärschlüssel ist dafür zwar gedacht, erfordert jedoch nicht immer die Existenz eines Primärschlüssels. Das Hinzufügen eines Primärschlüssels zu jeder Tabelle ist keine schlechte Vorgehensweise, da hierdurch eine eindeutige Zeilenidentifikation möglich ist, dies ist jedoch möglicherweise nicht erforderlich.

Um zuverlässige Beziehungen zwischen den Zeilen von zwei oder mehr Tabellen aufrechtzuerhalten, müssen Sie dies über Fremdschlüssel tun, weshalb in mindestens einigen Tabellen Primärschlüssel erforderlich sind. Das Hinzufügen eines Primärschlüssels zu jeder Tabelle erleichtert das Erweitern des Datenbankentwurfs, wenn neue Tabellen oder Beziehungen zu vorhandenen Daten hinzugefügt werden müssen. Vorausplanung ist immer eine gute Sache.

Grundsätzlich (harte Regel vielleicht) sollte sich der Wert eines Primärschlüssels während der gesamten Lebensdauer seiner Zeile nicht ändern. Es ist ratsam anzunehmen, dass sich alle Geschäftsdaten in einer Reihe im Laufe ihrer Lebensdauer ändern. Daher sind alle Geschäftsdaten ein schlechter Kandidat für einen Primärschlüssel. Aus diesem Grund ist etwas Abstraktes wie eine automatisch inkrementierte Ganzzahl oft eine gute Idee. Automatisch inkrementierte Ganzzahlen haben jedoch ihre Grenzen.

Wenn Ihre Daten nur in Ihrer Datenbank gespeichert sind, sind automatisch inkrementierte Ganzzahlen in Ordnung. Wie in anderen Antworten bereits erwähnt, führen automatisch inkrementierte Ganzzahlen jedoch zu schlechten Primärschlüsseln, wenn Sie möchten, dass Ihre Daten freigegeben, synchronisiert oder auf andere Weise außerhalb Ihrer Datenbank gespeichert werden. Eine bessere Wahl ist eine Guid (auch bekannt als "universell eindeutige ID").

Zenilogix
quelle
2

Die Frage und viele der Antworten übersehen den wichtigen Punkt, dass sich alle natürlichen Schlüssel für jede Tabelle ausschließlich im logischen Schema für die Datenbank und alle Ersatzschlüssel für jede Tabelle ausschließlich im physischen Schema für die Datenbank befinden. In anderen Antworten werden nur die relativen Vorteile von ganzzahligen gegenüber GUID-Ersatzschlüsseln erörtert, ohne die Gründe für die ordnungsgemäße Verwendung von Ersatzschlüsseln zu erläutern.

Übrigens: Vermeiden wir die Verwendung des schlecht definierten und ungenauen Begriffs Primärschlüssel . Es ist ein Artefakt vorrelationaler Datenmodelle, das zuerst (unklug) in das relationale Modell übernommen und dann von verschiedenen RDBMS-Anbietern wieder in den physischen Bereich übernommen wurde. Seine Verwendung dient nur dazu, die Semantik zu verwirren.

Beachten Sie aus dem relationalen Modell, dass jede Tabelle eine vom Benutzer sichtbare Gruppe von Feldern haben muss, die als natürlicher Schlüssel bezeichnet werden und jede Zeile der Tabelle eindeutig identifizieren , damit das logische Datenbankschema die erste normale Form aufweist . In den meisten Fällen ist ein solcher natürlicher Schlüssel leicht zu identifizieren, aber gelegentlich muss ein solcher Schlüssel konstruiert werden, sei es als ein Gleichstandsfeld oder auf andere Weise. Ein solcher konstruierter Schlüssel ist jedoch immer noch für den Benutzer sichtbar und befindet sich daher immer im logischen Schema der Datenbank.

Im Gegensatz dazu befindet sich jeder Ersatzschlüssel in einer Tabelle ausschließlich im physischen Schema der Datenbank (und muss daher sowohl aus Sicherheitsgründen als auch zur Aufrechterhaltung der Datenbankintegrität für Datenbankbenutzer vollständig unsichtbar sein). Der einzige Grund für die Einführung eines Ersatzschlüssels ist die Behebung von Leistungsproblemen bei der physischen Wartung und Verwendung der Datenbank. ob es sich dabei um Joins, Replikationen, mehrere Hardwarequellen für Daten oder andere handelt.

Da der einzige Grund für die Einführung eines Ersatzschlüssels die Leistung ist, nehmen wir an, dass wir möchten, dass er performant ist. Wenn das vorliegende Leistungsproblem Joins ist, möchten wir unseren Ersatzschlüssel unbedingt so eng wie möglich gestalten (ohne die Hardware zu beeinträchtigen, sodass in der Regel kurze Ganzzahlen und Bytes herauskommen). Die Join-Leistung hängt von der minimalen Indexhöhe ab, daher ist eine 4-Byte-Ganzzahl eine natürliche Lösung. Wenn Ihr Leistungsproblem die Einfügerate ist, kann eine 4-Byte-Ganzzahl auch eine natürliche Lösung sein (abhängig von den internen Merkmalen Ihres RDBMS). Wenn Ihr Leistungsproblem für eine Tabelle die Replikation oder mehrere Datenquellen als eine andere Ersatzschlüsseltechnologie ist, ist möglicherweise eine GUID oder ein zweiteiliger Schlüssel (Host-ID + Ganzzahl) besser geeignet. Ich persönlich bin kein Favorit von GUIDs, aber sie sind praktisch.

Zusammenfassend lässt sich sagen, dass nicht alle Tabellen einen Ersatzschlüssel (von beliebigem Typ) erfordern . Sie sollten nur verwendet werden, wenn dies für die Leistung der betreffenden Tabelle als notwendig erachtet wird. Unabhängig davon, welche gängige Ersatzschlüssel- Technologie Sie bevorzugen, sollten Sie die tatsächlichen Anforderungen der Tabelle sorgfältig abwägen, bevor Sie eine Auswahl treffen. Das Ändern der Wahl der Ersatzschlüssel- Technologie für einen Tisch wird anstrengend sein. Dokumentieren Sie die Hauptleistungsmetrik für Ihre Tabelle, damit Ihre Nachfolger die getroffenen Entscheidungen verstehen.

Sonderfälle

  1. Wenn Ihre Geschäftsanforderungen eine fortlaufende Nummerierung von Transaktionen für Prüfzwecke (oder andere) Zwecke erfordern, ist dieses Feld kein Ersatzschlüssel. Es ist ein natürlicher Schlüssel (mit zusätzlichen Anforderungen). Aus der Dokumentation geht hervor, dass eine automatisch inkrementierende Ganzzahl nur Ersatzschlüssel generiert. Suchen Sie daher nach einem anderen Mechanismus, um diese zu generieren. Offensichtlich ist eine Art Monitor erforderlich, und wenn Sie Ihre Transaktionen von mehreren Standorten aus beziehen, ist ein Standort ein besonderer Standort, da er als Host-Standort für den Monitor festgelegt ist.

  2. Wenn Ihre Tabelle niemals mehr als 100 Zeilen enthält, ist die Indexhöhe irrelevant. Jeder Zugriff erfolgt über einen Tabellenscan. Allerdings sind Zeichenfolgenvergleiche für lange Zeichenfolgen immer noch viel teurer als der Vergleich einer 4-Byte-Ganzzahl und teurer als der Vergleich einer GUID.

  3. Eine Tabelle der Codewert durch ein verkeilte char (4) Code - Feld sollte als performante als eines mit einer 4-Byte - Ganzzahl sein. Obwohl ich keinen Beweis dafür habe, verwende ich die Annahme häufig und hatte nie Grund, sie zu bereuen.

Pieter Geerkens
quelle
-1

Es ist nicht nur keine gute Praxis, sondern wird in Bill Karwins SQL Antipatterns-Buch auch als Anti-Pattern beschrieben.

Nicht jede Tabelle benötigt einen Pseudoschlüssel - einen Primärschlüssel mit einem beliebigen Wert, der keinen semantischen Wert für das Modell hat - und es gibt keinen Grund, ihn immer aufzurufen id.

Pedro Werneck
quelle
dies scheint nicht alles zu bieten erhebliche über Punkte gemacht und erläutert vor 9 Antworten
gnat
2
und warum könnte das wichtig sein?
gnat
3
@gnat Da es sich um ein Buch über bewährte Methoden handelt, in dem die Frage direkt angesprochen wird. Ist das nicht offensichtlich?
Pedro Werneck
3
nicht das geringste. Die Google-Suche nach "Book SQL Best Practices" zeigt mir etwa 900.000 Links, warum sollte diese besonders wertvoll sein
gnat
1
@gnat Ich werde nicht den ganzen Tag streiten. Die Antwort gefällt dir nicht, dafür sind Downvotes da.
Pedro Werneck
-2

Dies ist ziemlich universell - ansonsten müssten Sie überprüfen, ob der Schlüssel tatsächlich eindeutig ist. Dies würde durch einen Blick auf alle anderen Schlüssel geschehen ... was zeitaufwändig wäre. Ein inkrementeller Schlüssel wird teuer, wenn sich Ihre Datensatznummer dem Wert für den Schlüsselüberlauf nähert.

Normalerweise mache ich die Zeiger offensichtlicher wie Feldnamen ref_{table}oder ähnliche Idee.

Wenn es nicht erforderlich ist, extern auf einen Datensatz zu verweisen, benötigen Sie keine ID.

Johnny V
quelle
Schlüssel-Rollover-Wert?
AJJ
Eine Ganzzahl ohne Vorzeichen hat einen Maximalwert von 4294967295, bevor durch Hinzufügen von 1 der Wert auf 0 verschoben wird. Denken Sie daran, dass der Zähler immer noch erhöht wird, wenn Sie einen Datensatz hinzufügen und anschließend löschen. Stellen Sie sicher, dass Sie unsigned intfür den Feldtyp verwenden, da sonst die Hälfte dieser Anzahl überschritten wird.
Johnny V
Integer Overflow - de.wikipedia.org/wiki/Integer_overflow
Johnny V
2
Wenn Sie viele Zeilen hinzufügen oder entfernen, läuft der automatische Inkrementierungszähler möglicherweise über.
Johnny V
1
Wie gehen die Leute mit Überschlägen um? Was ist, wenn es Datensätze mit einer niedrigen ID gibt, die nie gelöscht werden, aber Sie sich dem Ende nähern, an dem sich einige IDs am oberen Ende von 4294967295 befinden? Kann eine "Neuindizierung" durchgeführt werden?
AJJ
-2

Ich würde nicht sagen, dass es immer getan werden sollte. Ich habe hier einen Tisch ohne eindeutigen Schlüssel - und er benötigt keinen. Es ist ein Überwachungsprotokoll. Es wird nie ein Update geben, Abfragen geben alle Änderungen an dem zurück, was protokolliert wird, aber das ist das Beste, was vernünftigerweise getan werden kann, um eine fehlerhafte Änderung zu definieren. (Wenn der Code es könnte, hätte er ihn überhaupt nicht zugelassen!)

Loren Pechtel
quelle
-3

Ein automatischer Inkrementzähler für einen Primärschlüssel ist keine gute Idee. Das liegt daran, dass Sie zur Datenbank zurückkehren müssen, um den nächsten Schlüssel zu finden und diesen vor dem Einfügen Ihrer Daten um eins zu erhöhen.

Abgesehen davon würde ich im Allgemeinen alles verwenden, was die Datenbank für den Primärschlüssel bereitstellen kann, anstatt ihn als Teil der Anwendung zu haben.

Indem Sie die Datenbank nativ zur Verfügung stellen, kann sichergestellt werden, dass der Schlüssel für die Anforderungen eindeutig ist.

Natürlich unterstützen es nicht alle Datenbanken. In diesem Fall verwende ich im Allgemeinen eine Tabelle, in der Schlüsselbereiche gespeichert werden, und verwende hohe und niedrige Bereiche, die in der Anwendung verwaltet werden. Dies ist die leistungsstärkste Lösung, die ich finde, da Sie einen Bereich von 10000 Zahlen erhalten und diese in der Anwendungsinstanz automatisch inkrementieren. Eine andere Anwendungsinstanz kann einen anderen Bereich von Zahlen abrufen, mit denen gearbeitet werden soll. Sie benötigen ein ausreichend großes Primärschlüssel-Primitiv, z. B. ein 64-Bit-Long.

UUIDs werden nicht als Primärschlüssel verwendet, da die Kosten für das Erstellen und Speichern der UUIDs viel höher sind als das Inkrementieren eines langen Werts um eins. UUIDs beschäftigen sich immer noch mit dem Geburtstagsparadox, da theoretisch ein Duplikat entstehen kann.

Archimedes Trajano
quelle
3
Nein. Auto-Inkrement-Schlüssel bedeutet, dass die Inkrementierung des Schlüssels automatisch von der Datenbank durchgeführt wird. Manchmal (ich sehe Sie an, Oracle!) Benötigen Sie dazu eine Sequenz + Trigger-Kombination, aber Sie müssen nie den zuvor eingegebenen Wert für den Schlüssel nachschlagen, 1 hinzufügen und ihn dann verwenden.
SQB
Wenn Sie bei einigen Persistenz-Frameworks wie JPA den Wert des erstellten Schlüssels an den Aufrufer zurückgeben möchten, müssen Sie den Datensatz laden, um den Schlüssel anzuzeigen.
Archimedes Trajano