Nachteile der Verwendung eines nullbaren Fremdschlüssels anstelle der Erstellung einer Schnittstellentabelle

15

Angenommen, ich habe das folgende ER-Diagramm:

Bildbeschreibung hier eingeben

Wenn ich nun die Beziehung mit einem Fremdschlüssel von Schoolin darstelle Student, könnte ich NULLWerte haben (da a Student nicht zu a gehören muss School), zum Beispiel:

Bildbeschreibung hier eingeben

Der richtige Weg (basierend auf dem, was ich gelesen habe) ist es, eine Schnittpunkttabelle zu erstellen, um die Beziehung darzustellen, zum Beispiel:

Bildbeschreibung hier eingeben

Auf diese Weise können keine NULLWerte in der Tabelle vorhanden sein School_has_Student.

Was sind die Nachteile der Verwendung eines nullbaren Fremdschlüssels anstelle der Erstellung einer Schnittstellentabelle?


Bearbeiten:

Ich habe fälschlicherweise ( school_id, student_id) als Primärschlüssel für die School_has_StudentTabelle gewählt, wodurch die Beziehung viele-zu-viele wurde. Der richtige Primärschlüssel sollte gewesen sein student_id:

Bildbeschreibung hier eingeben

Tom
quelle
7
Es gibt keinen "richtigen" Weg. Es gibt genau den Weg, der am besten zu Ihren Bedürfnissen passt.
MetaFight
1
Ich stimme mit Doc über die falsche Prämisse überein, aber vielleicht ist es immer noch klar genug, um zu antworten?
MetaFight
Es gibt eine falsche Prämisse, aber es ist leicht genug, den Unterschied auszuräumen und zu erklären.
Ich habe meine enge Abstimmung zurückgenommen, aber der Satz "Der richtige Weg (basierend auf dem, was ich gelesen habe) ist es, eine Schnittmenge zu erstellen, um die Beziehung darzustellen." Erweckt den Eindruck, dass Sie uns mitteilen sollten, von welcher Strainge-Quelle Sie wissen, dass dies die ist. " der richtige Weg. In jedem Lehrbuch, das ich zuvor gelesen habe, ist der kanonische Weg für 1: n-Beziehungen ein einzelner Fremdschlüssel. Oder hast du etwas falsch verstanden?
Doc Brown
@ Doc Brown Ich erinnere mich nicht, wo ich es gelesen habe, aber ich bin sicher, dass es besagt, dass eine Kreuzungstabelle der richtige Weg war. Wie auch immer, können Sie mir den Namen eines Buches geben, das besagt, dass eine 1: n-Beziehung (mit optionaler Teilnahme auf der: 1-Seite) mit einem einzigen Fremdschlüssel dargestellt werden soll? Ich bin daran interessiert zu lesen, was sie zu diesem Thema sagen.
Tom

Antworten:

18

Die beiden Modelle repräsentieren unterschiedliche Beziehungen.

Mithilfe einer Verknüpfungstabelle modellieren Sie eine Viele-zu-Viele-Beziehung.

Mit einem einfachen Fremdschlüssel modellieren Sie eine Eins-zu-Viele-Beziehung.

Der Nachteil eines nullbaren Fremdschlüssels besteht darin, dass die Beziehung nicht als Viele-zu-Viele-Beziehung modelliert werden kann, wenn Sie dies versuchen.


Basierend auf Ihrer Bearbeitung der Frage teilen Sie die Schülertabelle effektiv in zwei Tabellen mit demselben Schlüssel auf. Ich sehe dies im Allgemeinen auf Tabellen, die viel zu viele Felder haben, so dass jemand sie in zwei Teile aufteilt, um sie besser handhaben zu können (ich nenne es ein Schwein, das Lippenstift auflegt).

Durch Aufteilen der Schülertabelle machen Sie die zweite Tabelle optional, da in der zweiten Tabelle kein Datensatz vorhanden sein muss. Das ist einem Feld sehr ähnlich, das nicht gesetzt werden muss, weil es null sein kann.

Wenn Sie eine Eins-zu-Viele-Beziehung wünschen, ist es weitaus besser, eine einzelne Tabelle zu verwenden und zuzulassen, dass die Schul-ID in der Schülertabelle null ist. Es gibt keinen Grund, Nullen in Feldern zu vermeiden, selbst für einen Fremdschlüssel. Das bedeutet, dass die Fremdbeziehung optional ist: Entwickler und Datenbankadministratoren wissen das genau, und das zugrunde liegende Datenbankmodul sollte auf jeden Fall einwandfrei funktionieren.

Machen Sie sich keine Sorgen, wenn Sie über Joins besorgt sind. Es gibt genau definierte Semantiken für die Arbeitsweise von Joins mit Nullfeldern. Wenn Sie eine einzelne Tabelle verwenden, können Sie zwei Tabellen anstelle von drei verknüpfen.


quelle
Wenn ich also eine Eins-zu-Viele-Beziehung modelliere (mit optionaler Teilnahme auf der: 1-Seite), sollte ich einen Fremdschlüssel verwenden, obwohl dieser NULLWerte haben kann ?
Tom
1
@ Tom ja, genau so modelliert man es. Obwohl es technisch möglich ist, eine Verknüpfungstabelle zu verwenden, ermöglicht das Datenmodell viele zu viele, sodass Sie Trigger und Datenbanklogik benötigen, um dies zu verhindern. Sie sind besser dran, wenn Sie die Beziehung so einschränken, dass keine falschen Daten hinzugefügt werden können.
1
Ich habe meine Frage bearbeitet. Ich habe nur student_ideinen Primärschlüssel in der School_has_StudentTabelle erstellt, wodurch die Beziehung eins zu viele blieb. Welche Nachteile hat diese Methode gegenüber der Verwendung eines Fremdschlüssels?
Tom
@ Tom Ich habe meine Antwort bearbeitet.
7

Sie haben oben in einem Kommentar geschrieben:

In dem Buch "Fundamentals of Database Systems" [...] heißt es, dass die Verwendung einer Schnittstellentabelle empfohlen wird, wenn die Fremdschlüsselspalte viele NULL-Werte enthält (z. B. 98% der Mitarbeiter) keine Abteilung leiten)

Wenn die Fremdschlüsselspalte viele NULL-Werte enthält, müssen Ihre Programme diese meist leere Spalte für jeden Datensatz, den sie verarbeiten, verarbeiten. Die Spalte wird wahrscheinlich etwas Speicherplatz belegen, obwohl sie in 98% aller Fälle leer ist. Das Abfragen der Beziehung bedeutet, dass die Spalte abgefragt wird, die Ihnen mehr Netzwerkverkehr bietet, und wenn Sie einen ORM verwenden, der Ihre Klassen aus Ihren Tabellen und Programmen generiert wird auch mehr Platz auf der Client-Seite benötigen als nötig. Durch die Verwendung einer Schnittstellentabelle wird dies vermieden. Es sind nur Verknüpfungsdatensätze erforderlich, bei denen der entsprechende Fremdschlüssel andernfalls nicht NULL wäre.

Wenn Sie dagegen nicht nur wenige NULL-Werte haben, sagen wir, dass 50% oder mehr Relationen nicht NULL sind. Wenn Sie eine Schnittstellentabelle verwenden, erhalten Sie den gegenteiligen Effekt - mehr Speicherplatz, höhere Komplexität, was zu mehr Netzwerkverkehr usw. führt.

Die Verwendung einer Schnittstellentabelle ist also nur eine Form der Optimierung, die nur für einen bestimmten Fall sinnvoll ist, und insbesondere heutzutage, wo Speicherplatz und Arbeitsspeicher billiger wurden, viel seltener benötigt wird. Beachten Sie, dass "Fundamentals of Database Systems" ursprünglich vor mehr als 20 Jahren geschrieben wurde (ich habe einen Verweis auf die zweite Ausgabe von 1994 gefunden), und ich vermute, dass die Empfehlung zu diesem Zeitpunkt bereits da war. Vor 1994 war die Speicherplatzoptimierung wahrscheinlich viel wichtiger als heute, da Massenspeicher noch teurer und Computer und Netzwerke viel langsamer waren als heute.

Als Randnotiz zu einem wählerischen Kommentar: Die obige Aussage versucht nur zu ahnen, was der Autor von "Fundamentals of Database Systems" mit seiner Empfehlung vor Augen hatte. Ich denke, er machte eine grobe, allgemeine Aussage, die für die meisten Systeme gültig ist. In einigen Datenbanken gibt es andere mögliche Optimierungen wie "Spalten mit geringer Dichte", die die Verwendung einer Schnittstellentabelle noch überflüssiger machen.

Verstehen Sie diese Empfehlung also nicht falsch. Das Buch sagt Ihnen nicht, dass Sie Kreuzungstabellen für {0,1}:nBeziehungen im Allgemeinen bevorzugen sollen oder - wie Sie geschrieben haben - dass dies der "richtige Weg" ist. Verwenden Sie Optimierungen wie diese, die Ihre Programme nur dann komplizierter machen, wenn Sie sie wirklich benötigen.

Doc Brown
quelle
Sie gehen viel von der Implementierung der Datenbank aus, vor allem, wenn man bedenkt, dass das OP keine bestimmte Datenbank erwähnt hat. Es ist mehr als wahrscheinlich, dass die Datenbank intelligent genug ist, um nur wenig Platz für Spalten mit geringer Dichte zu verwenden.
Gardenhead
@gardenhead: woran glaubst du, dass dies "mehr als wahrscheinlich" ist?
Doc Brown
Die Tatsache, dass es Datenbanken seit Jahrzehnten gibt, die in hohem Maße optimiert sind, da sie eine kritische Komponente der meisten Infrastrukturen darstellen.
Gardenhead
@gardenhead: hört sich für mich so an, als würden Sie sehr viel ungerechtfertigte Annahmen machen als ich. Trotzdem siehe meine Bearbeitung.
Doc Brown
2

Das konzeptionelle Modell wird so aussehen, was umso weniger unorthodox ist :

Bildbeschreibung hier eingeben

Das physikalische Modell wird so aussehen, was umso weniger verwirrend ist (die Leute werden denken, dass es M: M ist, wenn sie nicht genau hinsehen):

Bildbeschreibung hier eingeben

Mein Vorschlag:

Wenn Sie möchten, trennen viele Spalten (FK oder andere), die für die meisten Schüler nicht zutreffen, die Tabellen in Rollentabellen mit 1: 1 rels. Das liegt aber nicht daran, dass es sich um FK handelt, sondern daran, dass die Spalten nicht für die meisten Zeilen gelten.

Andernfalls sind nullfähige FK ein normaler Teil einer Datenbank und Join-Tabellen sind normalerweise für M: M-Rels.

1: 1-Rels werden häufig für Rollentabellen mit Spalten verwendet, die nur dann gelten, wenn die Entität von einem bestimmten Typ ist, und um BLOB-Spalten aus Leistungs- oder Speichergründen zu extrahieren. Das Vermeiden von Nullwerten in FKs ist dafür keine gebräuchliche Verwendung.

Bildbeschreibung hier eingeben

Tulains Córdova
quelle
2

Neben anderen Antworten möchte ich darauf hinweisen, dass ein Nullwert für den Fremdschlüssel nicht eindeutig ist. Heisst das:

1) Die Schule des Schülers (falls vorhanden) ist unbekannt (dies ist die Standardbedeutung von 'null' - Wert ist unbekannt)

2) Es ist bekannt, ob der Schüler eine Schule hat oder nicht, und sie haben keine

Wenn Sie die Standardbedeutung von null verwenden, wie würden Sie "Schüler hat keine Schule" in Ihrem Fremdschlüsselmodell darstellen? In diesem Fall müssten Sie wahrscheinlich einen Eintrag "Keine Schule" mit einer eigenen ID in der Schultabelle erstellen. (Nicht ideal)

Brad Thomas
quelle
2
Das Buch "Fundamentals of Database Systems" erwähnt, dass es 3 Interpretationen dafür gibt NULL, es kann bedeuten: 1) Unbekannter Wert. 2) Nicht verfügbar oder Wert einbehalten. 3) Nicht zutreffendes Attribut (Ich denke, diese Interpretation bedeutet, dass Sie einen NULLfür einen Fremdschlüssel angeben können ).
Tom
1
Das ist eine nützliche Liste, aber die Semantik von null (oder wirklich jedem Wert) kann vom Benutzer definiert werden. Dh es kann bedeuten, was der Designer sagt, dass es bedeutet, nicht auf diese Liste beschränkt. Die Frage ist, wie man verschiedene Bedeutungen unterscheidet, wenn mehr als eine benötigt wird (oder sogar ungewollt gespeichert wird)
Brad Thomas
Schlagen Sie also vor, eine Schnittstellentabelle zu erstellen, anstatt einen nullfähigen Fremdschlüssel zu verwenden?
Tom
@ Tom Ja, ich glaube, das ist in diesem Fall besser
Brad Thomas
@BradThomas - Um die gleiche Mehrdeutigkeit bei der Verwendung einer Kreuzungstabelle zu vermeiden, würden Sie Fall 2 (es ist bekannt, dass der Schüler keine Schule hat) durch einen Datensatz in der Kreuzungstabelle mit einer NULL-School_ID darstellen?
Andrew
1

Datenbanktabellen haben diese nette Sache, die Beschränkungen genannt wird. Es ist also sehr einfach, eine Kreuzungstabelle zu erstellen, in der nur 1 Schüler in der Tabelle, aber viele Schulen in der Tabelle angezeigt werden. Effektiv geben Sie ein

Theorie ist nett, aber am Ende werden Sie Ihre Datenbank nach den Fragen modellieren, die Sie stellen.

Wenn Sie häufig mit der Frage fragen möchten: "Welche Schüler sind in meiner Schule?", Möchten Sie wirklich die gesamte Schülertabelle abfragen oder eine einfache Schnittstellentabelle haben.

In Datenbanken: Optimieren Sie für die von Ihnen gestellten Fragen.

Pieter B
quelle
0

Es gibt einen Anwendungsfall, in dem die Verwendung einer dritten Tabelle tatsächlich sinnvoll sein kann. Das Beispiel mag rein hypothetisch erscheinen, aber ich hoffe, es verdeutlicht meinen Standpunkt gut. Nehmen wir an, Sie fügen der studentsTabelle weitere Spalten hinzu und beschließen, die Eindeutigkeit der Datensätze über einen zusammengesetzten Index für mehrere Spalten zu erzwingen. Es ist sehr wahrscheinlich, dass Sie auch die school_idSpalte einschließen müssen , und hier beginnen die Dinge chaotisch zu werden. Aufgrund der Art und Weise wurde SQL entworfen, mehrere identische Datensätze eingefügt , wo school_idist NULLmöglich sein wird. Aus technischer Sicht macht es durchaus Sinn, ist jedoch nicht intuitiv und kann zu unerwarteten Ergebnissen führen. Andererseits ist es einfach, die Eindeutigkeit der Kreuzungstabelle durchzusetzen.

Ich musste kürzlich eine solche "optionale" Beziehung modellieren, bei der die Anforderung einer Eindeutigkeitsbeschränkung auf eine Zeitstempelspalte zurückzuführen war. Das Verlassen des nullbaren Fremdschlüssels in der Tabelle führt plötzlich dazu, dass Datensätze mit demselben Zeitstempel eingefügt werden können (nehmen wir an, es handelt sich um einen Standarddatensatz für Datensätze, die noch nicht geprüft / genehmigt wurden). Der einzige Ausweg war das Entfernen nullfähige Spalte.

Wie Sie sehen, handelt es sich also um einen ziemlich speziellen Fall, und wie andere angemerkt haben, sind Sie mit allen NULLWerten in den meisten Fällen vollkommen einverstanden . Es hängt wirklich von den spezifischen Anforderungen Ihres Modells ab.

petkov.np
quelle
0

Zusätzlich zu den vielen guten Vorschlägen, die bereits eingereicht wurden, bin ich persönlich kein Fan von Fremdschlüsseln, es sei denn, sie sind wirklich notwendig. Zunächst gibt es die M: M-Beziehung, auf die Sie verweisen. Das Aufrufen eines Fremdschlüssels und damit das Abrufen dieser Tabellendaten in Ihre Abfragen führt zu einer höheren Komplexität und je nach Tabellengröße zu einer langsameren Leistung. Wie bereits erwähnt, können nullfähige FK-Felder nicht unterstützt werden und Probleme mit der Datenintegrität verursachen.

Wenn Sie einen Zustand definieren, in dem die Schule des Schülers unbekannt oder leer ist, werden diese Bedingungen durch NULL nicht unterschieden. (Wieder sind wir zur Datenintegrität zurückgekehrt.) Der Rollentabellenvorschlag von Tulains ist elegant und lässt Nullwerte sauber zu.

Aby Sheffer
quelle