it-swarm-eu.dev

Was ist los mit Fremdschlüsseln?

Ich erinnere mich, dass ich Joel Spolsky in Podcast 014 erwähnte, dass er kaum jemals einen Fremdschlüssel verwendet hatte (wenn ich mich richtig erinnere). Für mich sind sie jedoch sehr wichtig, um Duplikationen und nachfolgende Probleme mit der Datenintegrität in Ihrer Datenbank zu vermeiden.

Haben die Leute einige gute Gründe, warum (um eine Diskussion in Übereinstimmung mit den Stack Overflow-Prinzipien zu vermeiden)?

Edit: "Ich habe noch keinen Grund, einen Fremdschlüssel zu erstellen Mein erster Grund, einen einzurichten. "

247
ljs

Gründe für die Verwendung von Fremdschlüsseln:

  • du wirst keine verwaisten Reihen bekommen
  • sie können ein gutes Verhalten beim Löschen von Kaskaden erzielen, indem Sie Tabellen automatisch bereinigen
  • wenn Sie die Beziehungen zwischen Tabellen in der Datenbank kennen, kann das Optimierungsprogramm Ihre Abfragen für eine möglichst effiziente Ausführung planen, da es bessere Schätzungen zur Kardinalität von Joins abrufen kann.
  • FKs geben einen ziemlich großen Hinweis darauf, welche Statistiken in der Datenbank am wichtigsten sind, was wiederum zu einer besseren Leistung führt
  • sie ermöglichen alle Arten von automatisch generierter Unterstützung - ORMs können selbst generiert werden, Visualisierungstools können Nice-Schema-Layouts für Sie erstellen usw.
  • jemand, der neu im Projekt ist, wird schneller in den Fluss der Dinge geraten, da ansonsten implizite Beziehungen explizit dokumentiert werden

Gründe, Fremdschlüssel nicht zu verwenden:

  • sie sorgen dafür, dass der DB bei jeder CRUD -Operation extra funktioniert, da er die FK-Konsistenz überprüfen muss. Dies kann einen hohen Preis bedeuten, wenn Sie viel Abwanderung haben
  • durch das Erzwingen von Beziehungen geben FKs eine Reihenfolge an, in der Sie Dinge hinzufügen/löschen müssen, was dazu führen kann, dass die DB die Ausführung der gewünschten Aktionen ablehnt. (Zugegeben, in solchen Fällen versuchen Sie, eine verwaiste Zeile zu erstellen, und das ist normalerweise keine gute Sache.) Dies ist besonders schmerzhaft, wenn Sie große Stapelaktualisierungen durchführen und eine Tabelle vor der anderen laden, wobei die zweite Tabelle einen konsistenten Status erzeugt (sollten Sie dies jedoch tun, wenn die Möglichkeit besteht, dass die zweite Ladung fehlschlägt und Ihre Datenbank ist jetzt inkonsistent?).
  • manchmal wissen Sie bereits im Voraus, dass Ihre Daten schmutzig werden. Sie akzeptieren dies und möchten, dass die Datenbank dies akzeptiert
  • du bist nur faul :-)

Ich glaube (da bin ich mir nicht sicher!), Dass die meisten etablierten Datenbanken eine Möglichkeit bieten, einen Fremdschlüssel anzugeben, der nicht erzwungen wird und nur ein bisschen Metadaten enthält. Da die Nichtdurchsetzung jeden Grund auslöscht, FKs nicht zu verwenden, sollten Sie diesen Weg wahrscheinlich einschlagen, wenn einer der Gründe im zweiten Abschnitt zutrifft.

344
SquareCog

Dies ist eine Frage der Erziehung. Wenn Sie irgendwo in Ihrer schulischen oder beruflichen Laufbahn Zeit mit dem Füttern und Pflegen von Datenbanken verbracht haben (oder eng mit talentierten Mitarbeitern zusammengearbeitet haben), sind die Grundprinzipien von Entitäten und Beziehungen in Ihrem Denkprozess gut verankert. Zu diesen Grundlagen gehört, wie/wann/warum Schlüssel in Ihrer Datenbank angegeben werden (primäre, fremde und möglicherweise alternative). Es ist eine zweite Natur.

Wenn Sie jedoch in der Vergangenheit noch keine so gründlichen oder positiven Erfahrungen mit RDBMS-bezogenen Vorhaben gemacht haben, wurden Sie wahrscheinlich nicht mit solchen Informationen konfrontiert. Oder vielleicht umfasst Ihre Vergangenheit das Eintauchen in eine Umgebung, die lautstark datenbankfeindlich war (z. B. "Diese DBAs sind Idioten - wir wenige, wir haben nur wenige Java/c # -Code-Slinger ausgewählt, um den Tag zu retten"). In diesem Fall könnten Sie vehement dagegen sein zu den arkanen Plappern eines Dweebs, die dir sagen, dass FKs (und die Einschränkungen, die sie implizieren können) wirklich wichtig sind, wenn du nur zuhörst.

Fast allen wurde als Kind beigebracht, dass das Zähneputzen wichtig ist. Kommst du ohne aus? Sicher, aber irgendwo auf der ganzen Linie stehen Ihnen weniger Zähne zur Verfügung, als Sie es hätten tun können, wenn Sie nach jeder Mahlzeit geputzt hätten. Wenn Mütter und Väter genug für das Datenbankdesign und die Mundhygiene verantwortlich wären, würden wir dieses Gespräch nicht führen. :-)

79
Ed Lucas

Ich bin sicher, es gibt viele Anwendungen, mit denen Sie davonkommen können, aber es ist nicht die beste Idee. Sie können sich nicht immer darauf verlassen, dass Ihre Anwendung Ihre Datenbank ordnungsgemäß verwaltet, und das ehrliche Verwalten der Datenbank sollte für Ihre Anwendung keine große Rolle spielen.

Wenn Sie eine relationale -Datenbank verwenden, sollten anscheinend einige Beziehungen definiert sein. Leider scheint diese Einstellung (Sie brauchen keine Fremdschlüssel) von vielen Anwendungsentwicklern angenommen zu werden, die sich lieber nicht mit albernen Dingen wie Datenintegrität beschäftigen möchten (dies ist jedoch erforderlich, da ihre Unternehmen keine dedizierten Datenbankentwickler haben). Normalerweise haben Sie in Datenbanken, die nach diesen Typen zusammengesetzt sind, das Glück, nur Primärschlüssel zu haben;)

52
AlexCuse

Fremdschlüssel sind wesentlich für jedes relationale Datenbankmodell.

40
Galwegian

Ich benutze sie immer, erstelle dann aber Datenbanken für Finanzsysteme. Die Datenbank ist der kritische Teil der Anwendung. Wenn die Daten in einer Finanzdatenbank nicht vollständig korrekt sind, spielt es keine Rolle, wie viel Aufwand Sie in Ihren Code/Front-End-Entwurf stecken. Du verschwendest nur deine Zeit.

Es gibt auch die Tatsache, dass mehrere Systeme im Allgemeinen direkt mit der Datenbank verbunden sein müssen - von anderen Systemen, die nur Daten auslesen (Crystal Reports), bis zu Systemen, die Daten einfügen (nicht unbedingt unter Verwendung einer von mir entworfenen API; diese kann von einem geschrieben werden Langweiliger Manager, der gerade VBScript entdeckt hat und das SA Kennwort für die SQL-Box) hat. Wenn die Datenbank nicht so idiotensicher ist, wie es nur sein kann, tschüss Datenbank .

Wenn Ihre Daten wichtig sind, sollten Sie Fremdschlüssel verwenden, eine Reihe gespeicherter Prozeduren für die Interaktion mit den Daten erstellen und die bestmögliche Datenbank erstellen. Wenn Ihre Daten nicht wichtig sind, warum erstellen Sie zunächst eine Datenbank?

29
Ant

Update : Ich benutze jetzt immer Fremdschlüssel. Meine Antwort auf den Einwand "Sie haben das Testen erschwert" lautet "Schreiben Sie Ihre Komponententests, damit sie die Datenbank überhaupt nicht benötigen. Alle Tests, die die Datenbank verwenden, sollten sie ordnungsgemäß verwenden und Fremdschlüssel enthalten. Wenn die Einrichtung schmerzhaft ist, finden Sie einen weniger schmerzhaften Weg, um das Setup zu tun. "


Fremdschlüssel erschweren das automatisierte Testen

Angenommen, Sie verwenden Fremdschlüssel. Sie schreiben einen automatisierten Test, der besagt: "Wenn ich ein Finanzkonto aktualisiere, sollte darin eine Aufzeichnung der Transaktion gespeichert werden." In diesem Test beschäftigen Sie sich nur mit zwei Tabellen: accounts und transactions.

Allerdings hat accounts einen Fremdschlüssel für contracts, und contracts hat ein Fk für clients, und clients hat ein Fk für cities und cities haben ein fk zu states.

Jetzt können Sie Ihren Test in der Datenbank nicht mehr ausführen, ohne Daten in vier Tabellen einzurichten, die sich nicht auf Ihren Test beziehen .

Hierfür gibt es mindestens zwei mögliche Perspektiven:

  • "Das ist eine gute Sache: Ihr Test sollte realistisch sein, und diese Datenbeschränkungen werden in der Produktion bestehen."
  • "Das ist eine schlechte Sache: Sie sollten in der Lage sein, Teststücke des Systems zusammenzufassen, ohne andere Teile einzubeziehen. Sie können Integrationstests für das gesamte System hinzufügen."

Es kann auch möglich sein, Fremdschlüsselprüfungen vorübergehend zu deaktivieren, während Tests ausgeführt werden. Zumindest MySQL nterstützt dies .

19
Nathan Long

"Sie können das Löschen von Datensätzen umständlicher machen - Sie können den" Master "-Datensatz nicht löschen, wenn Datensätze in anderen Tabellen vorhanden sind, bei denen Fremdschlüssel diese Einschränkung verletzen würden."

Beachten Sie, dass der SQL-Standard Aktionen definiert, die ausgeführt werden, wenn ein Fremdschlüssel gelöscht oder aktualisiert wird. Die, die ich kenne, sind:

  • ON DELETE RESTRICT - Verhindert, dass Zeilen in der anderen Tabelle, die Schlüssel in dieser Spalte enthalten, gelöscht werden. Dies ist, was Ken Ray oben beschrieben hat.
  • ON DELETE CASCADE - Wenn eine Zeile in der anderen Tabelle gelöscht wird, löschen Sie alle Zeilen in dieser Tabelle, die darauf verweisen.
  • ON DELETE SET DEFAULT - Wenn eine Zeile in der anderen Tabelle gelöscht wird, setzen Sie alle Fremdschlüssel, die darauf verweisen, auf die Standardspalte.
  • ON DELETE SET NULL - Wenn eine Zeile in der anderen Tabelle gelöscht wird, setzen Sie alle Fremdschlüssel, die in dieser Tabelle auf sie verweisen, auf null.
  • ON DELETE NO ACTION - Dieser Fremdschlüssel kennzeichnet nur, dass es sich um einen Fremdschlüssel handelt. nämlich zur Verwendung in OR Mapper.

Dieselben Aktionen gelten auch für ON UPDATE.

Die Standardeinstellung scheint davon abzuhängen, welchen sql Server Sie verwenden.

14
Powerlord

@imphasing - das ist genau die Art von Einstellung, die Albträume bei der Instandhaltung hervorruft.

Warum, warum, ignorieren Sie die deklarative referenzielle Integrität, bei der die Daten garantiert mindestens konsistent sein können, zugunsten der sogenannten "Software-Durchsetzung", die bestenfalls eine schwache vorbeugende Maßnahme darstellt.

14
Ed Guiness

Es gibt einen guten Grund, sie nicht zu benutzen: Wenn Sie ihre Rolle nicht verstehen oder nicht wissen, wie man sie benutzt.

In den falschen Situationen können Fremdschlüsseleinschränkungen zu einer Wasserfallreplikation von Unfällen führen. Wenn jemand die falsche Aufzeichnung entfernt, kann das Rückgängigmachen eine Mammutaufgabe werden.

Umgekehrt können Einschränkungen, wenn Sie etwas entfernen müssen, alle Arten von Sperren verursachen, die Sie daran hindern.

12
Kent Fredric

Es gibt keine guten Gründe , sie nicht zu verwenden ... es sei denn, verwaiste Zeilen sind für Sie keine große Sache, denke ich .

11
Matt Rogish

Die größere Frage ist: Würden Sie mit verbundenen Augen fahren? So ist es, wenn Sie ein System ohne referenzielle Einschränkungen entwickeln. Beachten Sie, dass sich die Geschäftsanforderungen, das Anwendungsdesign, die entsprechenden logischen Annahmen im Code, die Logik selbst usw. ändern. Im Allgemeinen werden Einschränkungen in Datenbanken unter zeitgemäßen logischen Annahmen festgelegt, die für bestimmte logische Aussagen und Annahmen als richtig erscheinen.

Während des Lebenszyklus einer Anwendung schränken Referenz- und Datenprüfungen die Erfassung von Polizeidaten über die Anwendung ein, insbesondere wenn neue Anforderungen zu Änderungen logischer Anwendungen führen.

Zum Thema dieser Auflistung - Ein Fremdschlüssel "verbessert" von sich aus weder die Leistung noch "verschlechtert" er die Leistung unter dem Gesichtspunkt des Echtzeit-Transaktionsverarbeitungssystems signifikant. Es gibt jedoch aggregierte Kosten für die Einschränkungsprüfung im "Batch" -System mit hohem Volumen. Hier ist also der Unterschied zwischen Echtzeit- und Batch-Transaktionsprozess. Batch-Verarbeitung - bei der die durch Einschränkungsprüfungen verursachten Gesamtkosten eines sequenziell verarbeiteten Batches einen Leistungstreffer darstellen.

In einem gut konzipierten System würden Datenkonsistenzprüfungen "vor" der Verarbeitung eines Stapels durchgeführt (dennoch sind auch hier Kosten verbunden). Daher sind während der Ladezeit keine Fremdschlüsseleinschränkungsprüfungen erforderlich. Tatsächlich sollten alle Einschränkungen, einschließlich des Fremdschlüssels, vorübergehend deaktiviert werden, bis der Stapel verarbeitet wird.

QUERY PERFORMANCE - Wenn Tabellen mit Fremdschlüsseln verknüpft werden, beachten Sie, dass Fremdschlüsselspalten NICHT INDEXIERT sind (obwohl der jeweilige Primärschlüssel per Definition indiziert ist). Das Indizieren eines Fremdschlüssels, das Indizieren eines beliebigen Schlüssels und das Verknüpfen von Tabellen mit einem Index trägt zu einer besseren Leistung bei, und nicht das Verknüpfen mit einem nicht indizierten Schlüssel mit einer Fremdschlüsselbeschränkung.

Ändern der Themen Wenn eine Datenbank nur die Anzeige/Wiedergabe von Inhalten/usw. von Websites und das Aufzeichnen von Klicks unterstützt, ist eine Datenbank mit vollständigen Einschränkungen für alle Tabellen für solche Zwecke überlastet. Denk darüber nach. Die meisten Websites verwenden hierfür nicht einmal eine Datenbank. Verwenden Sie für ähnliche Anforderungen, bei denen Daten nur aufgezeichnet und nicht referenziert werden, eine speicherinterne Datenbank, für die keine Einschränkungen gelten. Dies bedeutet nicht, dass es kein Datenmodell, ja logisches Modell, aber kein physikalisches Datenmodell gibt.

4
jasbir L

Aus meiner Erfahrung ist es immer besser, die Verwendung von FKs in datenbankkritischen Anwendungen zu vermeiden. Ich würde den Leuten hier nicht widersprechen, die sagen, FKs sind eine gute Praxis, aber es ist nicht praktisch, wenn die Datenbank riesig ist und riesige CRUD-Operationen pro Sekunde hat. Ich kann teilen ohne zu benennen ... eine der größten Investmentbanken von hat keine einzige FK in Datenbanken. Diese Einschränkungen werden von Programmierern beim Erstellen von Anwendungen mit DB behandelt. Der Hauptgrund ist, dass bei jeder neuen CRUD mehrere Tabellen erstellt und für jede Einfügung/Aktualisierung überprüft werden müssen. Dies ist jedoch kein großes Problem bei Abfragen, die sich auf einzelne Zeilen beziehen, führt jedoch zu einer enormen Latenz bei der Verarbeitung Stapelverarbeitung, die jede große Bank als tägliche Aufgabe zu erledigen hat.

Es ist besser, FKs zu vermeiden, aber das Risiko muss von Programmierern gehandhabt werden.

3
Rachit

"Überprüfen Sie vor dem Hinzufügen eines Datensatzes, ob ein entsprechender Datensatz in einer anderen Tabelle vorhanden ist", lautet die Geschäftslogik.

Hier sind einige Gründe, warum Sie dies nicht in der Datenbank möchten:

  1. Wenn sich die Geschäftsregeln ändern, müssen Sie die Datenbank ändern. Die Datenbank muss in vielen Fällen den Index neu erstellen, was bei großen Tabellen langsam ist. (Zu den geänderten Regeln gehört: Gäste können Nachrichten posten oder Benutzer können ihr Konto löschen, obwohl sie Kommentare usw. gepostet haben.).

  2. Das Ändern der Datenbank ist nicht so einfach wie das Bereitstellen eines Software-Fixes durch Übertragen der Änderungen in das Produktions-Repository. Wir möchten vermeiden, die Datenbankstruktur so weit wie möglich zu ändern. Je mehr Geschäftslogik in der Datenbank vorhanden ist, desto höher ist die Wahrscheinlichkeit, dass die Datenbänke geändert werden müssen (und eine erneute Indizierung ausgelöst wird).

  3. TDD. In Unit-Tests können Sie die Datenbank durch Mocks ersetzen und die Funktionalität testen. Wenn Ihre Datenbank eine Geschäftslogik enthält, führen Sie keine vollständigen Tests durch und müssen zu Testzwecken entweder mit der Datenbank testen oder die Geschäftslogik im Code replizieren, um die Logik zu duplizieren und die Wahrscheinlichkeit zu erhöhen, dass die Logik in der Datenbank nicht funktioniert gleicher Weg.

  4. Wiederverwenden Ihrer Logik mit verschiedenen Datenquellen. Wenn in der Datenbank keine Logik vorhanden ist, kann meine Anwendung Objekte aus Datensätzen aus der Datenbank oder aus einem Webdienst, einer JSON-Datei oder einer anderen Quelle erstellen. Ich muss nur die Data Mapper-Implementierung austauschen und kann meine gesamte Geschäftslogik mit jeder Quelle verwenden. Wenn die Datenbank Logik enthält, ist dies nicht möglich und Sie müssen die Logik auf der Data-Mapper-Ebene oder in der Geschäftslogik implementieren. In jedem Fall benötigen Sie diese Überprüfungen in Ihrem Code. Wenn die Datenbank keine Logik enthält, kann ich die Anwendung an verschiedenen Speicherorten mit verschiedenen Datenbank- oder Flatfile-Implementierungen bereitstellen.

3
Tom B

Zusätzlicher Grund für die Verwendung von Fremdschlüsseln: - Ermöglicht eine umfassendere Wiederverwendung einer Datenbank

Zusätzlicher Grund, Fremdschlüssel NICHT zu verwenden: - Sie versuchen, einen Kunden an Ihr Tool zu binden, indem Sie die Wiederverwendung reduzieren.

3
Dan

Ich stimme den vorherigen Antworten darin zu, dass sie nützlich sind, um die Datenkonsistenz zu gewährleisten. Vor einigen Wochen gab es jedoch einen interessanten Beitrag von Jeff Atwood , in dem die Vor- und Nachteile normalisierter und konsistenter Daten besprochen wurden.

Kurz gesagt, eine denormalisierte Datenbank kann schneller sein, wenn große Datenmengen verarbeitet werden. Abhängig von der Anwendung ist Ihnen die genaue Konsistenz möglicherweise nicht wichtig, aber Sie müssen beim Umgang mit Daten viel vorsichtiger vorgehen, da dies bei der Datenbank nicht der Fall ist.

2

Die Clarify-Datenbank ist ein Beispiel für eine kommerzielle Datenbank ohne Primär- oder Fremdschlüssel.

http://www.geekinterview.com/question_details/18869

Das Lustige ist, dass die technische Dokumentation sehr umfangreich ist, um zu erklären, wie Tabellen zusammenhängen, welche Spalten verwendet werden müssen, um sie zu verbinden usw.

Mit anderen Worten, sie könnten haben die Tabellen mit expliziten Deklarationen (DRI) verknüpft, aber sie wollten nicht.

Infolgedessen ist die Clarify-Datenbank voller Inkonsistenzen und weist eine Underperformance auf.

Aber ich nehme an, es hat den Entwicklern die Arbeit erleichtert, da sie keinen Code schreiben müssen, um die referenzielle Integrität zu behandeln, z. B. vor dem Löschen oder Hinzufügen nach verwandten Zeilen suchen.

Und das ist meiner Meinung nach der Hauptvorteil, wenn eine relationale Datenbank keine Fremdschlüsseleinschränkungen enthält. Es erleichtert die Entwicklung, zumindest aus der Sicht des Teufels.

2
Ed Guiness

Ich kenne nur Oracle-Datenbanken, keine anderen, und ich kann feststellen, dass Fremdschlüssel für die Aufrechterhaltung der Datenintegrität unerlässlich sind. Vor dem Einfügen von Daten muss eine Datenstruktur erstellt und korrekt ausgeführt werden. Wenn das erledigt ist - und somit alle Primär- und Fremdschlüssel erstellt sind - ist die Arbeit erledigt!

Bedeutung: verwaiste Reihen? Das habe ich in meinem Leben noch nie gesehen. Es sei denn, ein schlechter Programmierer hat den Fremdschlüssel vergessen oder auf einer anderen Ebene implementiert. Beides sind - im Zusammenhang mit Oracle - gewaltige Fehler, die zu Datenvervielfältigungen, verwaisten Daten und damit zu Datenkorruption führen. Ich kann mir keine Datenbank ohne erzwungene FK vorstellen. Es sieht für mich nach Chaos aus. Es ist ein bisschen wie beim Unix-Berechtigungssystem: Stellen Sie sich vor, jeder ist root. Denken Sie an das Chaos.

Fremdschlüssel sind ebenso wichtig wie Primärschlüssel. Es ist wie zu sagen: Was ist, wenn wir Primärschlüssel entfernen? Nun, es wird ein totales Chaos geben. Das ist, was. Sie dürfen die Primär- oder Fremdschlüsselverantwortung nicht auf die Programmierebene verschieben, sie muss sich auf der Datenebene befinden.

Nachteile? Ja absolut ! Weil beim Einfügen noch viel mehr Prüfungen stattfinden werden. Wenn jedoch die Datenintegrität wichtiger ist als die Leistung, ist dies ein Kinderspiel. Das Problem mit der Leistung von Oracle hängt eher mit den Indizes zusammen, die mit PK und FK geliefert werden.

2
tvCa

Das Löschen von Datensätzen kann umständlicher werden. Sie können den "Master" -Datensatz nicht löschen, wenn Datensätze in anderen Tabellen vorhanden sind, bei denen Fremdschlüssel gegen diese Einschränkung verstoßen würden. Sie können Trigger verwenden, um kaskadierende Löschvorgänge durchzuführen.

Wenn Sie Ihren Primärschlüssel nicht richtig ausgewählt haben, wird die Änderung dieses Werts noch komplexer. Wenn ich zum Beispiel die PK meiner "Kunden" -Tabelle als Personennamen habe und diesen Schlüssel zu einer FK in der "Bestellungen" -Tabelle mache, ist es ein königlicher Schmerz, wenn der Kunde seinen Namen ändern möchte. aber das ist nur mieses Datenbankdesign.

Ich glaube, dass die Vorteile der Verwendung von firign-Schlüsseln die vermeintlichen Nachteile überwiegen.

1
Ken Ray

Ich muss die meisten Kommentare hier an zweiter Stelle setzen. Fremdschlüssel sind notwendige Elemente, um sicherzustellen, dass Sie über Daten mit Integrität verfügen. Mit den verschiedenen Optionen für ON DELETE und ON UPDATE können Sie einige der "Down Falls" umgehen, die hier in Bezug auf ihre Verwendung erwähnt werden.

Ich stelle fest, dass ich in 99% aller meiner Projekte FKs haben werde, um die Integrität der Daten durchzusetzen. Es gibt jedoch einige seltene Fälle, in denen ich Kunden habe, die ihre alten Daten aufbewahren MÜSSEN, unabhängig davon, wie schlimm sie sind. Aber dann verbringe ich viel Zeit damit, Code zu schreiben, der sowieso nur die gültigen Daten abruft, so dass es sinnlos wird.

1
Mitchel Sellers

Das Argument, das ich gehört habe, ist, dass das Front-End diese Geschäftsregeln haben sollte. Fremdschlüssel "fügen unnötigen Overhead hinzu", wenn Sie keine Einfügungen zulassen sollten, die Ihre Einschränkungen aufheben. Stimme ich dem zu Nein, aber das habe ich immer gehört.

EDIT: Ich vermute, er bezog sich auf Fremdschlüsselbeschränkungen , nicht auf Fremdschlüssel als Konzept.

1
lordscarlet

Das Überprüfen von Fremdschlüsseleinschränkungen erfordert einige CPU-Zeit, sodass einige Benutzer Fremdschlüssel weglassen, um zusätzliche Leistung zu erzielen.

1
remonedo

Wenn Sie absolut sicher sind, dass sich das zugrunde liegende Datenbanksystem in Zukunft nicht ändern wird, würde ich Fremdschlüssel verwenden, um die Datenintegrität sicherzustellen.

Aber hier ist ein weiterer sehr guter Grund, Fremdschlüssel überhaupt nicht zu verwenden:

Sie entwickeln ein Produkt, das verschiedene Datenbanksysteme unterstützen soll.

Wenn Sie mit dem Entity Framework arbeiten, das eine Verbindung zu vielen verschiedenen Datenbanksystemen herstellen kann, möchten Sie möglicherweise auch serverlose Open-Source-Datenbanken ohne Gebühren unterstützen. Möglicherweise unterstützen nicht alle dieser Datenbanken Ihre Fremdschlüsselregeln (Aktualisieren, Löschen von Zeilen ...).

Dies kann zu verschiedenen Problemen führen:

1.) Beim Erstellen oder Aktualisieren der Datenbankstruktur können Fehler auftreten. Möglicherweise treten nur stille Fehler auf, da Ihre Fremdschlüssel vom Datenbanksystem einfach ignoriert werden.

2.) Wenn Sie sich auf Fremdschlüssel verlassen, werden Sie wahrscheinlich weniger oder gar keine Datenintegritätsprüfungen in Ihrer Geschäftslogik durchführen. Wenn das neue Datenbanksystem diese Fremdschlüsselregeln nicht unterstützt oder sich nur anders verhält, müssen Sie Ihre Geschäftslogik neu schreiben.

Sie fragen sich vielleicht: Wer braucht unterschiedliche Datenbanksysteme? Nun, nicht jeder kann oder will sich einen vollwertigen SQL-Server auf seinem Rechner leisten. Dies ist Software, die gewartet werden muss. Andere haben bereits Zeit und Geld in ein anderes DB-System investiert. Serverlose Datenbanken eignen sich hervorragend für kleine Kunden auf nur einem Computer.

Niemand weiß, wie sich all diese DB-Systeme verhalten, aber Ihre Geschäftslogik mit Integritätsprüfungen bleibt immer gleich.

1
Michael

Ich stimme der Antwort von Dmitriy zu - sehr gut ausgedrückt.

Für diejenigen, die sich Sorgen über den Leistungsaufwand machen, den FKs häufig mit sich bringen, gibt es eine Möglichkeit (in Oracle), den Vorteil der FK-Einschränkung für das Abfrageoptimierungsprogramm zu nutzen, ohne den Kostenaufwand für die Gültigkeitsprüfung von Einschränkungen beim Einfügen, Löschen oder Aktualisieren. Das heißt, Sie erstellen die FK-Einschränkung mit den Attributen RELY DISABLE NOVALIDATE. Dies bedeutet, dass das Abfrageoptimierungsprogramm davon ausgeht, dass die Einschränkung beim Erstellen von Abfragen erzwungen wurde, ohne dass die Datenbank die Einschränkung tatsächlich erzwingt. Sie müssen hier sehr vorsichtig sein, um die Verantwortung zu übernehmen, wenn Sie eine Tabelle mit einer FK-Einschränkung wie dieser füllen, um absolut sicherzugehen, dass Ihre FK-Spalten keine Daten enthalten, die die Einschränkung verletzen, als würden Sie dies tun kann zu unzuverlässigen Ergebnissen bei Abfragen führen, die die Tabelle betreffen, für die diese FK-Einschränkung gilt.

Normalerweise verwende ich diese Strategie für einige Tabellen in meinem Data Mart-Schema, jedoch nicht in meinem integrierten Staging-Schema. Ich stelle sicher, dass für die Tabellen, aus denen ich Daten kopiere, bereits die gleiche Einschränkung erzwungen wurde, oder dass die ETL-Routine die Einschränkung erzwingt.

1
Mike McAllister

Ich habe dieses Argument auch gehört - von Leuten, die vergessen haben, einen Index für ihre Fremdschlüssel zu erstellen, und sich dann beschwert haben, dass bestimmte Vorgänge langsam waren (weil die Einschränkungsprüfung jeden Index ausnutzen könnte). Fazit: Es gibt keinen guten Grund, Fremdschlüssel nicht zu verwenden. Alle modernen Datenbanken unterstützen kaskadierte Löschvorgänge.

1
Arno

Wenn Sie nach den Standards ACID arbeiten möchten, ist es für mich wichtig, Fremdschlüssel zu haben, um die referenzielle Integrität sicherzustellen.

1
CodeRot

Viele der hier antwortenden Personen sind zu sehr von der Bedeutung der referenziellen Integrität abhängig, die über referenzielle Einschränkungen implementiert wird. Das Arbeiten mit großen Datenbanken mit referentieller Integrität funktioniert einfach nicht gut. Oracle scheint besonders schlecht darin zu sein, Löschvorgänge zu kaskadieren. Meine Faustregel lautet, dass Anwendungen die Datenbank niemals direkt aktualisieren und über eine gespeicherte Prozedur erfolgen sollten. Dies hält die Codebasis in der Datenbank und bedeutet, dass die Datenbank ihre Integrität beibehält.

Wenn viele Anwendungen möglicherweise auf die Datenbank zugreifen, treten aufgrund von Einschränkungen der referenziellen Integrität Probleme auf, die jedoch einer Kontrolle unterliegen.

Ein weiteres Problem besteht darin, dass Anwendungsentwickler möglicherweise sehr unterschiedliche Anforderungen haben, mit denen Datenbankentwickler möglicherweise nicht so vertraut sind.

1
Zak

Ich denke auch, dass Fremdschlüssel in den meisten Datenbanken eine Notwendigkeit sind. Der einzige Nachteil (neben dem Leistungsverlust, der mit einer erzwungenen Konsistenz einhergeht) ist, dass Benutzer mit einem Fremdschlüssel Code schreiben können, der davon ausgeht, dass ein funktionsfähiger Fremdschlüssel vorhanden ist. Das sollte niemals erlaubt sein.

Ich habe zum Beispiel gesehen, wie Leute Code geschrieben haben, der in die referenzierte Tabelle einfügt und dann versucht, Einfügungen in die referenzierte Tabelle vorzunehmen, ohne zu überprüfen, ob die erste Einfügung erfolgreich war. Wenn der Fremdschlüssel zu einem späteren Zeitpunkt entfernt wird, führt dies zu einer inkonsistenten Datenbank.

Sie haben auch nicht die Möglichkeit, beim Aktualisieren oder Löschen ein bestimmtes Verhalten anzunehmen. Sie müssen noch Ihren Code schreiben, um zu tun, was Sie wollen, unabhängig davon, ob ein Fremdschlüssel vorhanden ist. Wenn Sie davon ausgehen, dass Löschvorgänge kaskadiert werden, wenn dies nicht der Fall ist, schlagen Ihre Löschvorgänge fehl. Wenn Sie davon ausgehen, dass Aktualisierungen der referenzierten Spalten an die referenzierenden Zeilen weitergegeben werden, wenn dies nicht der Fall ist, schlagen Ihre Aktualisierungen fehl. Zum Schreiben von Code verfügen Sie möglicherweise nicht über diese Funktionen.

Wenn diese Funktionen aktiviert sind, emuliert Ihr Code sie trotzdem und Sie verlieren etwas an Leistung.

Also, die Zusammenfassung ... Fremdschlüssel sind unerlässlich, wenn Sie eine konsistente Datenbank benötigen. Es sollte niemals angenommen werden, dass Fremdschlüssel in dem von Ihnen geschriebenen Code vorhanden oder funktionsfähig sind.

1
Eric

Wowowo ...
Antworten überall. Eigentlich ist dies das komplizierteste Thema, dem ich je begegnet bin. Ich benutze FKs, wenn sie gebraucht werden, aber in der Produktionsumgebung verwende ich sie selten.

Hier ist, warum ich die Fks selten benutze:

1. Die meiste Zeit beschäftige ich mich mit großen Datenmengen auf kleinen Servern, um die Leistung zu verbessern. Ich muss die FKs entfernen. Denn wenn Sie FKs haben und das RDBMS erstellen, aktualisieren oder löschen, prüfen Sie zuerst, ob keine Einschränkungsverletzung vorliegt und ob Sie eine große Datenbank haben, die möglicherweise schwerwiegend ist

2. Manchmal muss ich Daten von anderen Orten importieren und da ich nicht sicher bin, wie gut sie strukturiert sind, lasse ich einfach die FKs fallen.

3. Falls Sie es mit mehreren DBs zu tun haben und einen Referenzschlüssel in einer anderen DB haben, funktioniert dies (wie bisher) erst, wenn Sie die FKs (datenbankübergreifende Beziehungen) entfernen.
4. Dies war auch der Fall, wenn Sie eine Anwendung schreiben, die sich auf einem beliebigen RDBMS befindet, oder wenn Sie möchten, dass Ihre DB in ein beliebiges RDBMS-System exportiert und importiert wird. In diesem Fall hat jedes spezifische RDBMS-System seine eigene Art, mit FKs umzugehen, und Sie werden es wahrscheinlich sein verpflichtet, die Verwendung von FKs fallen zu lassen.

5. Wenn Sie eine RDBMS-Plattform (ORMs) verwenden, wissen Sie, dass einige von ihnen je nach Lösung und Technik ihr eigenes Mapping anbieten, und es ist Ihnen egal, ob Sie die Tabellen und ihre FKs erstellen.

6. Vor dem letzten Punkt stehen Kenntnisse im Umgang mit Datenbanken, die über FKs verfügen, und das Wissen, eine Anwendung zu schreiben, die alle Aufgaben ohne FK 7 erledigt. Wie ich bereits sagte, hängt alles von Ihrem Szenario ab, falls dies nicht der Fall ist eine Barriere. Sie werden immer das Beste vom Besten haben wollen, das Sie bekommen können!


Dank euch allen!

Ein FK kann zu Problemen führen, wenn Sie historische Daten haben, die auf den Schlüssel verweisen (in einer Nachschlagetabelle), obwohl der Schlüssel nicht mehr verfügbar sein soll.
Natürlich besteht die Lösung darin, die Dinge von vornherein besser zu gestalten, aber ich denke an Situationen in der realen Welt, in denen Sie nicht immer die volle Kontrolle über die Lösung haben.
Zum Beispiel: Vielleicht haben Sie eine Nachschlagetabelle customer_type, das verschiedene Kundentypen auflistet - sagen wir, Sie müssen einen bestimmten Kundentyp entfernen, können jedoch (aus geschäftlichen Gründen) die Client-Software nicht aktualisieren, und niemand hat diese Situation bei der Entwicklung der Software in Betracht gezogen Wenn es sich um einen Fremdschlüssel in einer anderen Tabelle handelt, können Sie die Zeile möglicherweise nicht entfernen, obwohl Sie wissen, dass die historischen Daten, auf die sie verweist, irrelevant sind.
Nachdem Sie ein paar Mal damit verbrannt wurden, lehnen Sie sich wahrscheinlich von der Durchsetzung von Beziehungen ab.
(Ich sage nicht, dass dies gut ist - nenne nur einen Grund, warum du dich entscheiden kannst, FKs und DB-Beschränkungen im Allgemeinen zu vermeiden.)

0
hamishmcn

In einem Projekt, an dem ich gearbeitet habe, gab es oft eher implizite als explizite Beziehungen, sodass zahlreiche Tabellen in derselben Spalte verknüpft werden konnten.

Nehmen Sie die folgende Tabelle

Adresse

  • AddressId (PK)
  • EntityId
  • EntityType
  • Stadt
  • Zustand
  • Land
  • Etc..

Mögliche Werte für EntityType sind Employee, Company, Customer und die EntityId bezieht sich auf den Primärschlüssel der Tabelle, an der Sie interessiert waren.

Ich denke nicht wirklich, dass dies der beste Weg ist, um Dinge zu tun, aber es hat für dieses Projekt funktioniert.

0
Curtis

Wie viele Dinge ist es ein Kompromiss. Es ist eine Frage, wo Sie die Arbeit zur Überprüfung der Datenintegrität ausführen möchten:

(1) Verwenden eines Fremdschlüssels (ein einziger Punkt für die Konfiguration einer Tabelle, Feature ist bereits implementiert, getestet, funktioniert nachweislich)

(2) Überlassen Sie dies den Benutzern der Datenbank (möglicherweise aktualisieren mehrere Benutzer/Apps dieselbe Tabelle (n), was potenziell mehr Fehlerquellen und eine höhere Komplexität beim Testen bedeutet).

Es ist effizienter für die Datenbank (2), einfacher zu warten und mit (1) weniger Risiko.

0
Jen A

Ich werde wiederholen, was Dmitriy gesagt hat, aber einen Punkt hinzufügen.

Ich arbeitete an einem Batch-Abrechnungssystem, bei dem große Zeilenmengen in über 30 Tabellen eingefügt werden mussten. Wir durften keine Datenpumpen (Oracle) durchführen, also mussten wir Bulk-Inserts durchführen. Diese Tabellen enthielten Fremdschlüssel, aber wir hatten bereits sichergestellt, dass sie keine Beziehungen unterbrechen.

Vor dem Einfügen deaktivieren wir die Fremdschlüsseleinschränkungen, damit Oracle die Einfügungen nicht für immer ausführt. Nachdem das Einfügen erfolgreich war, aktivieren wir die Einschränkungen erneut.

PS: In einer großen Datenbank mit vielen Fremdschlüsseln und untergeordneten Zeilendaten für einen einzelnen Datensatz können Fremdschlüssel manchmal fehlerhaft sein, und Sie möchten möglicherweise das kaskadierende Löschen nicht zulassen. Für uns im Abrechnungssystem würde es zu lange dauern und zu anstrengend für die Datenbank sein, wenn wir kaskadierende Löschvorgänge durchführen, sodass wir den Datensatz nur mit einem Feld in der Haupttreiber- (übergeordneten) Tabelle als fehlerhaft markieren.

0
typicalrunt

Wenn in DB2 MQTs (Materialized Query Tables) verwendet werden, sind Fremdschlüsseleinschränkungen erforderlich, damit der Optimierer den richtigen Plan für eine bestimmte Abfrage auswählen kann. Da sie die Kardinalitätsinformationen enthalten, verwendet das Optimierungsprogramm die Metadaten in hohem Maße, um eine MQT zu verwenden oder nicht.

0
Senthil

Ein gutes Prinzip des Datenstrukturdesigns besteht darin, sicherzustellen, dass jedes Attribut einer Tabelle oder eines Objekts einer wohlverstandenen Einschränkung unterliegt. Dies ist wichtig, da es weniger wahrscheinlich ist, dass Programmfehler durch fehlerhafte Daten verursacht werden, wenn Sie oder Ihr Programm auf gültige Daten in der Datenbank zählen können. Sie verbringen auch weniger Zeit mit dem Schreiben von Code, um Fehlerzustände zu behandeln, und es ist wahrscheinlicher, dass Sie Fehlerbehandlungscode im Voraus schreiben.

In vielen Fällen können diese Einschränkungen zur Kompilierungszeit definiert werden. In diesem Fall können Sie einen Filter schreiben, um sicherzustellen, dass das Attribut immer innerhalb des Bereichs liegt, oder der Versuch, das Attribut zu speichern, schlägt fehl.

In vielen Fällen können sich diese Einschränkungen jedoch zur Laufzeit ändern. Beispielsweise können Sie eine "Autos" -Tabelle haben, die "Farbe" als Attribut hat, das anfänglich die Werte "Rot", "Grün" und "Blau" annimmt. Während der Ausführung des Programms ist es möglich, dieser anfänglichen Liste gültige Farben hinzuzufügen, und neu hinzugefügte "Autos" können jede Farbe in der aktuellen Liste der Farben annehmen. Darüber hinaus soll diese aktualisierte Liste von Farben in der Regel einen Neustart des Programms überstehen.

Um Ihre Frage zu beantworten, stellt sich heraus, dass Fremdschlüssel die einfachste und prägnanteste Lösung für das Problem sind, wenn Sie eine Anforderung an Datenbeschränkungen haben, die sich zur Laufzeit ändern können und diese Änderungen einen Neustart des Programms überstehen müssen. Die Entwicklungskosten sind das Hinzufügen einer Tabelle (z. B. "Farben", eine Fremdschlüsseleinschränkung für die Tabelle "Autos" und ein Index) und die Laufzeitkosten die zusätzliche Tabellensuche für die aktuellen Farben Um die Daten zu validieren, werden diese Laufzeitkosten normalerweise durch Indizieren und Zwischenspeichern verringert.

Wenn Sie für diese Anforderungen keine Fremdschlüssel verwenden, müssen Sie Software schreiben, um die Liste zu verwalten, gültige Einträge zu suchen, sie auf der Festplatte zu speichern, die Daten effizient zu strukturieren, wenn die Liste groß ist, und sicherstellen, dass Aktualisierungen der Liste nicht durchgeführt werden die Listendatei beschädigen, seriellen Zugriff auf die Liste gewähren, falls mehrere Leser und/oder Schreiber vorhanden sind, und so weiter. Sie müssen viele RDBMS-Funktionen implementieren.

0
Jay Godse

Ich fand es immer faul, sie nicht zu benutzen. Mir wurde beigebracht, dass es immer getan werden sollte. Aber dann habe ich nicht auf Joels Diskussion gehört. Er könnte einen guten Grund gehabt haben, ich weiß es nicht.

0
Kilhoffer

Q uite oft erhalten wir die Fehler mit FK-Einschränkungen Kann eine untergeordnete Zeile nicht hinzufügen oder aktualisieren: eine Fremdschlüssel-Einschränkung schlägt fehl Angenommen, es gibt zwei Tabellen inventory_source und contract_lines, und wir verweisen inventory_source_id in contract_lines von inventory_source und nehmen an, wir möchten einen Datensatz aus inventory_source löschen und der Datensatz ist bereits in contract_lines vorhanden Wenn Sie die PK-Spalte aus der Basistabelle löschen möchten, erhalten Sie Fehler für FK-Einschränkungen. Sie können dies mit den unten aufgeführten Schritten vermeiden.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Wir können es mit den folgenden Schritten überwinden:

  1. Durch Löschen oder Aktualisieren der Zeile aus der inventory_source werden die übereinstimmenden Zeilen in der contract_lines-Tabelle automatisch gelöscht oder aktualisiert. Dies wird als Kaskadenlöschung oder -aktualisierung bezeichnet.
  2. Eine andere Möglichkeit besteht darin, die Spalte "inventory_source_id" in der Tabelle "contract_lines" auf NULL zu setzen, wenn ein entsprechender Datensatz in der Tabelle "inventory_source" gelöscht wird.
  3. Wir können die übergeordnete Tabelle zum Löschen oder Aktualisieren einschränken, mit anderen Worten, Sie können die Lösch- oder Aktualisierungsoperation für die Tabelle inventory_source ablehnen.
  4. Der Versuch, einen Primärschlüsselwert zu löschen oder zu aktualisieren, kann nicht fortgesetzt werden, wenn in der Tabelle, auf die verwiesen wird, ein entsprechender Fremdschlüsselwert vorhanden ist.
0
Vikas Kukreti