Eine einzelne Primärschlüsselsequenz in einer Datenbank gemeinsam nutzen?

13

Ist es eine akzeptable Praxis, eine einzelne Sequenz als Primärschlüssel für alle Tabellen zu verwenden (anstatt dass ein Primärschlüssel für eine bestimmte Tabelle eindeutig ist, ist er für alle Tabellen eindeutig)? Ist dies der Fall, ist dies objektiv besser als die Verwendung einer einzelnen Primärschlüsselsequenz für mehrere Tabellen.

Ich bin ein Junior-Softwareentwickler und kein DBA. Daher lerne ich immer noch viele der Grundlagen eines guten Datenbankdesigns.

Bearbeiten: Für den Fall, dass sich jemand wundert, habe ich kürzlich eine Kritik eines Datenbankdesigns von einem der Datenbankadministratoren unseres Unternehmens gelesen, in der er erwähnte, dass das Design keinen einzigen Primärschlüssel für die gesamte Datenbank verwendet habe, was sich anders anhörte als was Ich habe bisher gelernt.

Edit2: Um eine Frage in den Kommentaren zu beantworten, ist dies für Oracle 11g, aber ich habe mich auf einer nicht datenbankspezifischen Ebene gefragt. Wenn diese Frage von der Datenbank abhängt, würde ich gerne wissen, warum, aber in einem solchen Fall würde ich nach einer Oracle-spezifischen Antwort suchen.

Lawtonfogle
quelle
2
Normalerweise ist es aus Performancegründen eine schreckliche Idee.
Philᵀᴹ
1
Tatsächlich besteht ein größerer Vorteil darin, dass jede Tabelle über einen eigenen, unabhängigen Primärschlüsselbereich verfügt. Aber nur, wenn Sie sich eine Reihe von IDs ansehen, können Sie sagen, dass dies Accounts, PurchaseHeader usw. sind. Dies erfordert einige Einstellungen und (wie bei jeder speziellen Sache) eine fortlaufende Pflege und Fütterung. (Ja, ich habe vor vielen Jahren mit einem solchen System gearbeitet.)
RLF
Welches DBMS verwenden Sie? Orakel? Postgres? DB2?
a_horse_with_no_name
1
Ist es möglich, dass Sie falsch verstanden haben, was er meinte? Vielleicht war er nicht so wörtlich?
James Ryan
Bedeutete der Unternehmens-DBA tatsächlich, dass in keiner der Tabellen Primärschlüsselfelder vorhanden sind?
Max Vernon

Antworten:

12

Akzeptabel? Sicher. Verbreitet? Nein, wohltuend? Zweifelhaft.

In meinem alten Job haben wir ein System geerbt, in dem es einen zentralen Sequenzgenerator gab (dies war ein SQL Server-System, lange bevor SEQUENCEes in SQL Server 2012 eingeführt wurde). Es war eigentlich kein Leistungsengpass und sollte es auch nicht sein, wenn Sie nicht Hunderttausende von Werten pro Sekunde generieren. Aber es machte den gesamten Code viel komplexer, als es sein musste, ohne guten Grund. Die Absicht des Entwurfs war es, sicher zu sein, dass, wenn einem Element im System ein ID-Wert von 12 zugewiesen wurde, nur eines im System die ID 12 haben könnte. Dies schien mir ziemlich stumpf zu sein und ich habe es nie verstanden. Wenn ich einen Kunden mit CustomerID = 12 habe, warum hindert mich das daran, eine Bestellung mit OrderID = 12 zu haben?

Ich sehe die Nützlichkeit eines zentralen Sequenzgenerators, wenn Sie über mehrere Systeme verfügen und aus diesen mehreren Systemen IDs für einen bestimmten Entitätstyp (z. B. einen Kunden oder einen Auftrag) generieren. Eine zentrale Sequenz kann neue Werte an mehrere Systeme ausgeben, ohne dass dies ein Engpass ist (nur ein einzelner Fehlerpunkt) und ohne dass befürchtet wird, dass zwei Systeme dieselbe ID generieren.

Aaron Bertrand
quelle
Wenn Sie zwischen so etwas und der Verwendung eindeutiger Kennungen als Primärschlüssel wählen müssten, hätten Sie eine Präferenz (obwohl die Antwort wahrscheinlich "es hängt davon ab" ist)? Es scheint, als würde eine GUID das Problem auf die gleiche Weise umgehen, mit der Ausnahme, dass Sie eine Standardimplementierung erhalten würden, anstatt Ihren eigenen zentralisierten Primärschlüsselgenerator rollen zu müssen. Die Verwendung einer Sequenz in SQL 2012 würde natürlich beides bewirken, aber wenn jemand eine ältere Version verwendet?
SqlRyan
2
@SqlRyan Ich muss verstehen, warum eine OrderID von einer CustomerID völlig verschieden sein muss. Ich würde mit ziemlicher Sicherheit keine GUID dafür verwenden. Das Einrichten von IDENTITY-Bereichen ist möglicherweise besser (Kunden beginnen bei 1, Bestellungen beginnen bei 1000000 usw.), und es werden Warnmeldungen angezeigt, wenn Sie sich der Erschöpfung des Bereichs nähern.
Aaron Bertrand
1
@SqlRyan - Die Verwendung einer schlecht implementierten GUID als gruppierter Primärschlüssel kann alle möglichen Probleme verursachen. Wie Aaron sagte, passt IDENTITY viel besser zu dem Zweck.
Max Vernon
In einem früheren System wurde eine einzige Sequenz in der gesamten Datenbank verwendet, um zu ermöglichen, dass ein Fremdschlüssel auf zahlreiche verschiedene Tabellen anstatt auf eine einzelne Tabelle verweist Mit 12 Jahren wussten Sie, dass sie auf dasselbe zeigten, ohne nach dem möglichen Tisch suchen zu müssen, auf den sie zeigten. Eine 13 in derselben Spalte kann möglicherweise der Primärschlüssel für eine andere Tabelle sein. Ich persönlich fühle mich mit diesem Designstil sehr unwohl.
Lawtonfogle
@AaronBertrand Oder verwenden Sie alternativ einfache Ganzzahlbezeichner und hängen Sie Code an den Anfang an, wenn diese dem Kunden zugewandt sind. z.B. I1337, C1337 eindeutig eine Rechnung oder ein Kunde
JamesRyan
6

Die Idee hat sich in einer sehr komplexen Datenbank bewährt, in der Personen versehentlich mit der falschen Spalte zu einer Tabelle hinzugefügt werden und ungültige Zeilen erhalten können, nur weil die INT-IDs identisch sind.

Wir haben uns für sequentielle GUIDs als Primärschlüssel entschieden, um einige der Fallstricke der Indexfragmentierung von GUIDs zu vermeiden. Leider sind sie ziemlich groß.

SQL Server kann sequenzielle GUIDs über einen Standard generieren, der die Funktion newSequentialID () aufruft, sodass keine Tabelle der zu verwaltenden Schlüssel und kein Blockierungsengpass vorhanden sind.

Dadurch haben wir eindeutige IDs für die gesamte Datenbank erhalten, und zwar für das gesamte Unternehmen, da diese wirklich eindeutig sind.

Der Preis ist natürlich der Platzbedarf und das Problem, wenn Sie versuchen, die Daten in ein Data Warehouse / Cube zu übertragen, in dem Geschwindigkeit / Größe auf der Verwendung kleinerer Ganzzahlschlüssel beruhen.

Ich bin davon überzeugt, dass wir viele Fehler in unserer App aufgrund ihrer Verwendung vermieden haben.

RayG
quelle
4

Ich kann mir nicht vorstellen, was der Grund für die einzelne Sequenz in allen Tabellen sein könnte. Es entsteht lediglich ein Engpass bei der Generierung neuer Werte.

Egal wie gering der Aufwand für die Generierung sequenzieller Schlüsselwerte ist, der Generator ist eine einzelne Ressource, auf die synchronisiert werden muss. Je mehr Anfragen es gibt, desto höher ist die Wahrscheinlichkeit, dass einige Anfragende warten müssen, bis sie an der Reihe sind. Es ist offensichtlich, dass auf den einzelnen Sequenzgenerator, der von allen Tabellen gemeinsam genutzt wird, häufiger von mehr Clients zugegriffen wird, wodurch mehr Konkurrenz erzeugt wird als auf einen der mehreren Generatoren. Der Konflikt kann sich verschärfen, wenn Geschäftsregeln den generierten Werten Einschränkungen auferlegen, z. B. das Fehlen von Lücken oder eine strikte Reihenfolge, oder in einer Cluster-Datenbank.

Auch mit dem effizientesten Sequenzgenerator dort wird eine Arbeitsbelastung , die untolerable Streit verursacht.

mustaccio
quelle
2
Möglicherweise möchten Sie Details hinzufügen, wie der Engpass entsteht und warum dies eine schlechte Idee ist.
Max Vernon
2

Der Zweck von PrimaryKey in Datenbanktabellen besteht in erster Linie darin, die Eindeutigkeit von Daten zu erzwingen, die eindeutig sein sollen, da nicht alle Workflows abgedeckt werden können und sichergestellt werden kann, dass keine Daten dupliziert werden. Der zweite Grund ist, dass PK häufig auch der Hauptkandidat für den Clustered-Index für Tabellen ist, sodass der Abruf von Daten beschleunigt wird, wenn / wo diese Spalten in ausgewählten Abfragen ordnungsgemäß verwendet werden.

Die Verwendung einer Sequenznummer als Primärschlüssel ist dieselbe wie bei jeder Tabelle mit der Spalte Identität, und nur diese Spalte wird in PrimaryKey verwendet. Eine einzige Sequenznummer in der Datenbank zu haben, muss eine bestimmte Verwendung haben, aber aus der Sicht von PrimaryKey verstehe ich den Grund nicht. In einem der Datawarehouse-Projekte, an denen ich gearbeitet habe, haben wir beispielsweise die Spalte LoadBatchID, und von ETL bis zum Reporting haben 50% aller Tabellen diese Spalte, aber an einigen Stellen hat sie eine andere Bedeutung. Wir haben den eindeutigen Prozess als Zahlengenerator verwendet, um sicherzustellen, dass wir keine Konflikte finden und um zu der ursprünglichen Datei zurückzukehren, von der die Daten stammen und was in den einzelnen ETL-Phasen passiert.

Anup Shah
quelle
2

Ich nehme an, ein Grund dafür wäre, wenn alle Entitäten von einer übergeordneten Entität geerbt würden. Angenommen, Sie möchten in der Lage sein, einen Kommentar zu einem beliebigen Entitätstyp zu verfassen:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Normalerweise wird das nicht gemacht. .

Keine Ahnung über die Leistungsmerkmale.

Neil McGuigan
quelle