Primärschlüssel oder eindeutiger Index?

127

Bei der Arbeit haben wir eine große Datenbank mit eindeutigen Indizes anstelle von Primärschlüsseln und alles funktioniert einwandfrei.

Ich entwerfe eine neue Datenbank für ein neues Projekt und habe ein Dilemma:

In der DB-Theorie ist der Primärschlüssel ein grundlegendes Element, das ist in Ordnung, aber was sind in REAL-Projekten die Vor- und Nachteile beider?

Was verwenden Sie in Projekten?

EDIT: ... und was ist mit Primärschlüsseln und Replikation auf MS SQL Server?

Cicik
quelle
2
Es gibt einige zusätzliche Überlegungen, die hier diskutiert werden (wenn auch mit dem zusätzlichen Kontext eines Deckungsindex) - dba.stackexchange.com/questions/21554/…
StuartLC
ANMERKUNG: SQLite unterscheidet sich darin, dass der Primärschlüssel aufgrund eines Legacy-Problems gegen den allgemeinen Standard null sein kann. sqlite.org/lang_createtable.html
Bitinn

Antworten:

168

Was ist ein eindeutiger Index?

Ein eindeutiger Index für eine Spalte ist ein Index für diese Spalte, der auch die Einschränkung erzwingt, dass in dieser Spalte nicht zwei gleiche Werte in zwei verschiedenen Zeilen vorhanden sein dürfen. Beispiel:

CREATE TABLE table1 (foo int, bar int);
CREATE UNIQUE INDEX ux_table1_foo ON table1 (foo); - Erstellen Sie einen eindeutigen Index für foo.

INSERT INTO table1 (foo, bar) VALUES (1, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (2, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (3, 1); -- OK
INSERT INTO table1 (foo, bar) VALUES (1, 4); - schlägt fehl!

Doppelter Eintrag '1' für Schlüssel 'ux_table1_foo'

Die letzte Einfügung schlägt fehl, weil sie den eindeutigen Index für die Spalte verletzt, foowenn versucht wird, den Wert 1 zum zweiten Mal in diese Spalte einzufügen.

In MySQL erlaubt eine eindeutige Einschränkung mehrere NULL-Werte.

Es ist möglich, einen eindeutigen Index für mehrere Spalten zu erstellen.

Primärschlüssel versus eindeutiger Index

Dinge, die gleich sind:

  • Ein Primärschlüssel impliziert einen eindeutigen Index.

Dinge, die anders sind:

  • Ein Primärschlüssel impliziert auch NICHT NULL, aber ein eindeutiger Index kann nullwertfähig sein.
  • Es kann nur einen Primärschlüssel geben, es können jedoch mehrere eindeutige Indizes vorhanden sein.
  • Wenn kein Clustered-Index definiert ist, ist der Primärschlüssel der Clustered-Index.
Mark Byers
quelle
4
Beachten Sie, dass ein eindeutiger Index ein Index für eine Spalte ist, der nicht ganz genau ist, da ein eindeutiger Index oder Primärschlüssel mehr als eine Spalte enthalten kann.
Alex Jasmin
2
@Alexandre Jasmin: Danke behoben. Der Teil über mehrere Spalten wird später erwähnt.
Mark Byers
In Bezug auf Nullen erlauben Ansi-Standards mehrere Nullwerte in einem Datensatz mit einer eindeutigen Einschränkung, und dies ist auch die Implementierung unter Oracle und PostgreSQL. Ich glaube, dass SQL Server nur einen Nullwert zulässt.
David Aldridge
3
aber ich habe es trotzdem nicht verstanden, wie wann man einen Primärschlüssel verwendet oder wann man einen eindeutigen Index verwendet? oder können beide in den gleichen Situationen sein.
Amit
33

Sie können es so sehen:

Ein Primärschlüssel ist einzigartig

Ein eindeutiger Wert muss nicht die Darstellung des Elements sein

Bedeutung?; Nun, ein Primärschlüssel wird verwendet, um das Element zu identifizieren. Wenn Sie eine "Person" haben, möchten Sie eine persönliche Identifikationsnummer (SSN oder eine solche) haben, die für Ihre Person primär ist.

Auf der anderen Seite hat die Person möglicherweise eine E-Mail, die eindeutig ist, die Person jedoch nicht identifiziert.

Ich habe immer Primärschlüssel, auch in Beziehungstabellen (der Mitteltabelle / Verbindungstabelle), die ich möglicherweise habe. Warum? Nun, ich folge gerne einem Standard beim Codieren. Wenn die "Person" eine Kennung hat, hat das Auto eine Kennung, dann sollte die Person -> Auto auch eine Kennung haben!

Filip Ekberg
quelle
In Ihren Beziehungstabellen: Meinen Sie, Sie führen eine neue Spalte mit einem künstlichen Primärschlüssel (z. B. einer Ganzzahl) ein oder verwenden Sie einen zusammengesetzten Primärschlüssel (person_id, car_id)?
3
Primärschlüssel (person_id, car_id) wäre der beste. Aber ich erstelle im Allgemeinen eine neue Spalte, sicher, dass es etwas Overhead gibt, aber ich habe es für gut gehalten. Sie wissen nie, ob Sie sich in einem späteren Szenario auf eine bestimmte Beziehung beziehen möchten.
Filip Ekberg
1
Der andere Ersatzschlüssel für Ihre Composite- / Join-Tabelle erleichtert die Wartung manueller Aufgaben.
Robert C. Barth
2
Sie benötigen nur einen Primärschlüssel, wenn Sie Kinder haben möchten. Warum eine Spalte und eine Sequenz hinzufügen, wenn der Wert nirgendwo erscheint, wenn der Wert für nichts verwendet wird? Es ist eine Arbeit, um zu verhindern, dass Access nach einer PK fragt. Erstellen Sie eine PK, wenn Sie den Datensatz eines Kindes identifizieren müssen, da dies sonst eine Verschwendung ist.
3
Wenn es nichts mit Beziehungen zu tun hat, womit hat es dann zu tun? Sie zeigen auf ein Feld und sagen, das ist primär. Und? Was passiert dann? Und wenn es kein natürliches pk gibt, füge ich eine Spalte und eine Sequenz und einen Trigger hinzu und alles, weil ____? Einige müssen nur primär sein. Ich meide Regeln ohne Grund.
10

Fremdschlüssel funktionieren sowohl mit eindeutigen Einschränkungen als auch mit Primärschlüsseln. Aus Online-Büchern:

Eine FOREIGN KEY-Einschränkung muss nicht nur mit einer PRIMARY KEY-Einschränkung in einer anderen Tabelle verknüpft sein. Es kann auch definiert werden, um auf die Spalten einer UNIQUE-Einschränkung in einer anderen Tabelle zu verweisen

Für die Transaktionsreplikation benötigen Sie den Primärschlüssel. Aus Online-Büchern:

Für die Transaktionsreplikation veröffentlichte Tabellen müssen einen Primärschlüssel haben. Wenn sich eine Tabelle in einer Transaktionsreplikationspublikation befindet, können Sie keine Indizes deaktivieren, die Primärschlüsselspalten zugeordnet sind. Diese Indizes werden für die Replikation benötigt. Um einen Index zu deaktivieren, müssen Sie zuerst die Tabelle aus der Publikation löschen.

Beide Antworten beziehen sich auf SQL Server 2005.

Jonas Lincoln
quelle
DAS macht mir zum Teufel Angst (erstes Zitat). Warum? Ich habe eine Personentabelle mit einer willkürlichen ID, die meine PK ist, aber ich entscheide mich, Telefon, E-Mail und SSN ein UK hinzuzufügen. Ich denke, ich würde auf jede Flexibilität verzichten, die Sie aus Gründen der Konsistenz erhalten könnten.
5

Die Wahl, wann ein Ersatzprimärschlüssel im Gegensatz zu einem natürlichen Schlüssel verwendet werden soll, ist schwierig. Antworten wie immer oder nie sind selten nützlich. Ich finde, dass es von der Situation abhängt.

Als Beispiel habe ich die folgenden Tabellen:

CREATE TABLE toll_booths (
    id            INTEGER       NOT NULL PRIMARY KEY,
    name          VARCHAR(255)  NOT NULL,
    ...
    UNIQUE(name)
)

CREATE TABLE cars (
    vin           VARCHAR(17)   NOT NULL PRIMARY KEY,
    license_plate VARCHAR(10)   NOT NULL,
    ...
    UNIQUE(license_plate)
)

CREATE TABLE drive_through (
    id            INTEGER       NOT NULL PRIMARY KEY,
    toll_booth_id INTEGER       NOT NULL REFERENCES toll_booths(id),
    vin           VARCHAR(17)   NOT NULL REFERENCES cars(vin),
    at            TIMESTAMP     DEFAULT CURRENT_TIMESTAMP NOT NULL,
    amount        NUMERIC(10,4) NOT NULL,
    ...
    UNIQUE(toll_booth_id, vin)
)

Wir haben zwei Entitätstabellen ( toll_boothsund cars) und eine Transaktionstabelle ( drive_through). Die toll_boothTabelle verwendet einen Ersatzschlüssel, da sie kein natürliches Attribut enthält, dessen Änderung nicht garantiert werden kann (der Name kann leicht geändert werden). Die carsTabelle verwendet einen natürlichen Primärschlüssel, da sie einen unveränderlichen eindeutigen Bezeichner ( vin) hat. Die drive_throughTransaktionstabelle verwendet einen Ersatzschlüssel zur einfachen Identifizierung, unterliegt jedoch auch einer eindeutigen Einschränkung für die Attribute, die zum Zeitpunkt des Einfügens des Datensatzes garantiert eindeutig sind.

http://database-programmer.blogspot.com hat einige großartige Artikel zu diesem speziellen Thema.

Aekeus
quelle
4

Primärschlüssel haben keine Nachteile.

Um nur einige Informationen zu den Antworten von @MrWiggles und @Peter Parker hinzuzufügen: Wenn die Tabelle beispielsweise keinen Primärschlüssel hat, können Sie in einigen Anwendungen keine Daten bearbeiten (sie sagen am Ende, dass etw ohne Daten nicht bearbeitet / gelöscht werden kann Primärschlüssel). Postgresql erlaubt, dass sich mehrere NULL-Werte in der Spalte UNIQUE befinden. PRIMARY KEY erlaubt keine NULL-Werte. Auch einige ORM, die Code generieren, können Probleme mit Tabellen ohne Primärschlüssel haben.

AKTUALISIEREN:

Soweit ich weiß, ist es nicht möglich, Tabellen ohne Primärschlüssel in MSSQL zu replizieren, zumindest nicht ohne Probleme ( Details ).

empi
quelle
Wenn neue Zeilen eingefügt oder diese Spalte aktualisiert wird, entsteht ein Overhead.
3

Wenn etwas ein Primärschlüssel ist, wird abhängig von Ihrer DB-Engine die gesamte Tabelle nach dem Primärschlüssel sortiert. Dies bedeutet, dass die Suche auf dem Primärschlüssel viel schneller ist, da keine Dereferenzierung durchgeführt werden muss, wie dies bei jeder anderen Art von Index der Fall ist. Abgesehen davon ist es nur Theorie.

Ray Hidayat
quelle
3
Die Tabelle wird nach dem Clustered-Index sortiert, nicht unbedingt nach dem Primärschlüssel.
Ray Booysen
1
Es kommt einfach so vor, dass die meisten Leute ihren Primärschlüssel als Clustered-Index festlegen.
Ray Booysen
Was wir wissen, ist oft eine wirklich schlechte Idee, es sei denn, wir mögen Hotspots und unausgeglichene Indexbäume in unseren Tabellen, natürlich ...
Mike Woodhouse
1
Es ist nicht immer eine wirklich schlechte Idee. Kennen Sie Ihre Daten, kennen Sie Ihr RDBMS, wissen Sie, was die Auswahlmöglichkeiten bedeuten. Selten ist die Wahl IMMER gut oder schlecht. Wenn IMMER einer wäre, würde die Datenbank dies vorschreiben oder verbieten. Sie geben Ihnen die Wahl, weil "es kommt darauf an".
2

Zusätzlich zu den anderen Antworten erfordern einige Datenbanken und Systeme möglicherweise, dass eine Primärdatenbank vorhanden ist. Eine Situation fällt mir ein; Bei Verwendung der Unternehmensreplikation mit Informix muss eine PK vorhanden sein, damit eine Tabelle an der Replikation teilnehmen kann.

tddmonkey
quelle
2

Solange Sie NULL für einen Wert nicht zulassen, sollten sie gleich behandelt werden, aber der Wert NULL wird in Datenbanken unterschiedlich behandelt (AFAIK MS-SQL erlaubt nicht mehr als einen (1) NULL-Wert, mySQL und Oracle erlauben dies , wenn eine Spalte EINZIGARTIG ist) Sie müssen diese Spalte also NICHT NULL EINZIGARTIGER INDEX definieren

Peter Parker
quelle
1
MS-SQL erlaubt wie jedes RDBMS mehrere NULL-Werte in einer Spalte mit einem eindeutigen Index. Stellen Sie sich das so vor: NULL ist kein Wert. Wenn Sie also einen zweiten NULL einfügen, stimmt dieser niemals mit einem vorhandenen überein. Der Ausdruck (NULL == NULL) wird nicht als wahr oder falsch ausgewertet, sondern als NULL ausgewertet.
Gregmac
Danke Gregmac, ich war mir nicht sicher, ob MS dem folgt. Ich erinnerte mich an einige MS Quirks damit, jedoch vor einigen Jahren (vor 2000) und könnte auch ein alter Access-DB- Husten sein
Peter Parker
2

In der relationalen Datentheorie gibt es keinen Primärschlüssel, daher muss Ihre Frage auf praktischer Ebene beantwortet werden.

Eindeutige Indizes sind nicht Teil des SQL-Standards. Die spezielle Implementierung eines DBMS bestimmt, welche Konsequenzen die Deklaration eines eindeutigen Index hat.

Wenn Sie in Oracle einen Primärschlüssel deklarieren, wird in Ihrem Namen ein eindeutiger Index erstellt, sodass die Frage fast umstritten ist. Ich kann Ihnen nichts über andere DBMS-Produkte erzählen.

Ich bevorzuge die Angabe eines Primärschlüssels. Dies hat zur Folge, dass NULL-Werte in den Schlüsselspalten verboten und Duplikate verboten werden. Ich bevorzuge es auch, REFERENCES-Einschränkungen zu deklarieren, um die Integrität der Entität durchzusetzen. In vielen Fällen beschleunigt das Deklarieren eines Index für die Coulmn eines Fremdschlüssels die Verknüpfungen. Diese Art von Index sollte im Allgemeinen nicht eindeutig sein.

Walter Mitty
quelle
Ein Primärschlüssel in MS SQL Server ist immer sowohl EINZIGARTIG als auch NICHT NULL - z. B. ist es wirklich nur ein eindeutiger Index, aber mit der zusätzlichen Einschränkung, dass er nicht NULL sein kann.
marc_s
Oracle kann eine eindeutige Einschränkung mit einem nicht eindeutigen Index erzwingen. Ich wäre überrascht, wenn MSSS dies nicht könnte. Zu sagen "es ist wirklich nur ein eindeutiger Index" ist ein schlechter Dienst.
"In vielen Fällen beschleunigt das Deklarieren eines Index für die Coulmn eines Fremdschlüssels die Verknüpfung." Dies ist in einer Data-Warehousing-Welt, in der Hash-Joins bevorzugt werden, wenn verfügbar, fast immer nicht der Fall.
JAC2703
Das OP erwähnte keine Lagerhäuser. Ich bin nicht sicher, wie Hash-Loins auf SQL Server funktionieren. Wie viel Arbeit kann zum Zeitpunkt der Lageraktualisierung erledigt werden?
Walter Mitty
2

Es gibt einige Nachteile von CLUSTERED INDEXES gegenüber UNIQUE INDEXES.

Wie bereits erwähnt, ordnet ein CLUSTERED INDEX die Daten in der Tabelle physisch an.

Dies bedeutet, dass bei physischen Einfügungen oder Löschungen in einer Tabelle mit einem Clustered-Index die physische Tabelle jedes Mal (fast abhängig von Ihrem Füllfaktor) aktualisiert werden muss, um sortiert zu bleiben.

In relativ kleinen Tabellen ist dies in Ordnung, aber wenn Sie zu Tabellen mit Daten im Wert von GB gelangen und Einfügungen / Löschungen die Sortierung beeinflussen, treten Probleme auf.

Nico Bester
quelle
Was ist dann der Vorteil? sortierte Abfragen sind schneller? Ist dies besser für einen Anwendungsfall, wenn Sie die meisten Ihrer Daten einmal (oder selten) schreiben und ständig abfragen?
Buffalo
1

Ich erstelle fast nie eine Tabelle ohne numerischen Primärschlüssel. Wenn es auch einen natürlichen Schlüssel gibt, der eindeutig sein sollte, setze ich auch einen eindeutigen Index darauf. Verknüpfungen sind bei Ganzzahlen schneller als mehrspaltige natürliche Schlüssel. Daten müssen sich nur an einer Stelle ändern (natürliche Schlüssel müssen in der Regel aktualisiert werden, was in Beziehungen zwischen Primärschlüssel und Fremdschlüssel eine schlechte Sache ist). Wenn Sie eine Replikation benötigen, verwenden Sie eine GUID anstelle einer Ganzzahl. Zum größten Teil bevorzuge ich jedoch einen Schlüssel, der vom Benutzer gelesen werden kann, insbesondere wenn er zur Unterscheidung zwischen John Smith und John Smith angezeigt werden muss.

Ich erstelle selten einen Ersatzschlüssel, wenn ich eine Verbindungstabelle habe, die in eine Viele-zu-Viele-Beziehung verwickelt ist. In diesem Fall deklariere ich beide Felder als Primärschlüssel.

HLGEM
quelle
„Ich erstelle fast nie eine Tabelle ohne numerischen Primärschlüssel“: Warum immer numerisch? Ein Primärschlüssel muss nicht numerisch sein (auch nicht AUTO_INCREMENT).
Hibou57
@ Hinou57, weil ich festgestellt habe, dass natürliche Schlüssel selten tatsächlich einzigartig sind und fast immer veränderbar sind. Darüber hinaus sind Verknüpfungen bei Intergern im Allgemeinen viel schneller als Verknüpfungen bei natürlichen Varcahrr-Schlüsseln oder schlechteren zusammengesetzten Schlüsseln. Ich würde sie die meiste Zeit nicht benutzen. Dies kann je nach Art der Informationen variieren, die Sie in Ihrer Datenbank speichern. Nach meiner persönlichen Erfahrung habe ich jedoch festgestellt, dass natürliche Schlüssel im Laufe der Zeit äußerst unzuverlässig sind.
HLGEM
Danke für die Antwort HLGEM. Was meinst du mit unzuverlässig? Performance? (Ich hoffe, das ist keine Frage der Zuverlässigkeit im Sinne der Datenintegrität). Ich bin ein bisschen überrascht von Ihren Worten, da die Verwendung von Ganzzahlschlüsseln oder natürlicheren Schlüsseln wie Short VARCHAR wahrscheinlich nur einen winzigen Unterschied macht, da Hashing auch bei den einfachsten DB-Engines überall verwendet wird.
Hibou57
Sie sind in vielen Fällen unzuverlässig, weil sie nicht zuverlässig einzigartig sind, obwohl sie es sein sollen. Sie sind unzuverlässig, da sie sich ändern und dies Millionen von Datensätzen in einem Uopdate betreffen kann. Dies ist meine Erfahrung mit dem Anzeigen und Verwalten oder Abfragen von Daten aus oder dem Importieren von Daten aus Hunderten von Datenbanken, in denen Daten zu vielen verschiedenen Arten von Informationen gespeichert sind.
HLGEM
1

Nach meinem Verständnis sind ein Primärschlüssel und ein eindeutiger Index mit einer Nicht-Null-Einschränkung identisch (*). und ich nehme an, einer wählt den einen oder anderen, je nachdem, was in der Spezifikation explizit angegeben oder impliziert wird (eine Frage dessen, was Sie ausdrücken und explizit durchsetzen möchten). Wenn es Eindeutigkeit und nicht Null erfordert, machen Sie es zu einem Primärschlüssel. Wenn es einfach passiert, dass alle Teile eines eindeutigen Index nicht null sind, ohne dass dies erforderlich ist, machen Sie ihn einfach zu einem eindeutigen Index.

Der einzige verbleibende Unterschied besteht darin, dass Sie möglicherweise mehrere eindeutige Indizes haben, die nicht null sind, während Sie nicht mehrere Primärschlüssel haben können.

(*) Mit Ausnahme eines praktischen Unterschieds: Ein Primärschlüssel kann der standardmäßige eindeutige Schlüssel für einige Vorgänge sein, z. B. das Definieren eines Fremdschlüssels. Ex. Wenn man einen Fremdschlüssel definiert, der auf eine Tabelle verweist, und den Spaltennamen nicht angibt, wenn die referenzierte Tabelle einen Primärschlüssel hat, ist der Primärschlüssel die referenzierte Spalte. Andernfalls muss die Spalte, auf die verwiesen wird, explizit benannt werden.

Andere hier haben die DB-Replikation erwähnt, aber ich weiß nichts darüber.

Hibou57
quelle
0

Der eindeutige Index kann einen NULL-Wert haben. Es wird NON-CLUSTERED INDEX erstellt. Der Primärschlüssel darf keinen NULL-Wert enthalten. Es wird ein CLUSTERED INDEX erstellt.

Chirag
quelle
0

In MSSQL sollten die Primärschlüssel monoton ansteigen, um die beste Leistung für den Clustered-Index zu erzielen. Daher ist eine Ganzzahl mit Identitätseinfügung besser als jeder natürliche Schlüssel, der möglicherweise nicht monoton ansteigt.

Markus
quelle
-1

Wenn es nach mir ginge ...

Sie müssen die Anforderungen der Datenbank und Ihrer Anwendungen erfüllen.

Durch Hinzufügen einer automatisch inkrementierenden Ganzzahl- oder langen ID-Spalte zu jeder Tabelle als Primärschlüssel werden die Datenbankanforderungen berücksichtigt.

Anschließend fügen Sie der Tabelle mindestens einen weiteren eindeutigen Index zur Verwendung durch Ihre Anwendung hinzu. Dies wäre der Index für employee_id oder account_id oder customer_id usw. Wenn möglich, sollte dieser Index kein zusammengesetzter Index sein.

Ich würde Indizes für mehrere Felder einzeln gegenüber zusammengesetzten Indizes bevorzugen. Die Datenbank verwendet die einzelnen Feldindizes immer dann, wenn die where-Klausel diese Felder enthält. Sie verwendet jedoch nur einen Verbund, wenn Sie die Felder in genau der richtigen Reihenfolge angeben. Dies bedeutet, dass das zweite Feld in einem zusammengesetzten Index nur verwendet werden kann, wenn Sie dies angeben sowohl die erste als auch die zweite in Ihrer where-Klausel.

Ich bin alle für die Verwendung von berechneten oder Funktionstyp-Indizes - und würde empfehlen, sie über zusammengesetzte Indizes zu verwenden. Es macht es sehr einfach, den Funktionsindex zu verwenden, indem dieselbe Funktion in Ihrer where-Klausel verwendet wird.

Dies kümmert sich um Ihre Anwendungsanforderungen.

Es ist sehr wahrscheinlich, dass andere nicht-primäre Indizes tatsächlich Zuordnungen dieses Indexschlüsselwerts zu einem Primärschlüsselwert sind, nicht zu Rowid (). Dies ermöglicht physische Sortiervorgänge und Löschvorgänge, ohne dass diese Indizes neu erstellt werden müssen.

Rodney P. Barbati
quelle