Nach meiner Erfahrung enthielten viele der Projekte, die ich in der Vergangenheit gelesen habe, keine Beziehungsdefinitionen in der Datenbank, sondern sie definierten sie nur im Quellcode. Ich frage mich also, welche Vor- und Nachteile es hat, Beziehungen zwischen Tabellen in der Datenbank und im Quellcode zu definieren. Und die umfassendere Frage betrifft andere erweiterte Funktionen in modernen Datenbanken wie Kaskaden, Trigger, Prozeduren ... In meinen Gedanken gibt es einige Punkte:
In der Datenbank:
Korrigieren Sie Daten aus dem Design. Verhindern Sie Anwendungsfehler, die ungültige Daten verursachen können.
Reduzieren Sie den Netzwerk-Roundtrip zur Anwendung beim Einfügen / Aktualisieren von Daten, da die Anwendung mehr Abfragen durchführen muss, um die Datenintegrität zu überprüfen.
Im Quellcode:
Flexibler.
Besser bei der Skalierung auf mehrere Datenbanken, da die Beziehung manchmal datenbankübergreifend sein kann.
Mehr Kontrolle über die Datenintegrität. Die Datenbank muss nicht jedes Mal überprüft werden, wenn die Anwendung Daten ändert (Komplexität kann O (n) oder O (n log n) (?) Sein). Stattdessen wird es an die Anwendung delegiert. Und ich denke, der Umgang mit der Datenintegrität in der Anwendung führt zu ausführlicheren Fehlermeldungen als die Verwendung der Datenbank. Beispiel: Wenn Sie einen API-Server erstellen, die Beziehungen in der Datenbank definieren und ein Fehler auftritt (z. B. dass die Entität, auf die verwiesen wird, nicht vorhanden ist), wird eine SQL-Ausnahme mit einer Meldung angezeigt. Die einfache Möglichkeit besteht darin, 500 an den Client zurückzugeben, wenn ein "Interner Serverfehler" vorliegt und der Client keine Ahnung hat, was falsch läuft. Oder der Server kann die Nachricht analysieren, um herauszufinden, was falsch ist, was meiner Meinung nach eine hässliche, fehleranfällige Methode ist. Wenn Sie dies der Anwendung überlassen,
Gibt es noch etwas?
Bearbeiten: Wie Kilian betont, ist mein Standpunkt zu Leistung und Datenintegrität sehr falsch. Also habe ich bearbeitet, um meinen Punkt dort zu korrigieren. Ich verstehe vollkommen, dass es effizienter und robuster sein wird, wenn die Datenbank damit umgeht. Bitte überprüfen Sie die aktualisierte Frage und denken Sie darüber nach.
Edit: danke euch allen. Die Antworten, die ich erhalten habe, weisen alle darauf hin, dass die Einschränkungen / Beziehungen in der Datenbank definiert werden sollten. :). Ich habe noch eine Frage, da diese Frage nicht in den Geltungsbereich dieser Frage fällt. Ich habe sie gerade als separate Frage veröffentlicht: Behandle Datenbankfehler für API-Server . Bitte hinterlassen Sie einige Einblicke.
Antworten:
TL; DR: Beziehungseinschränkungen sollten in die Datenbank aufgenommen werden.
Ihre Bewerbung ist nicht groß genug.
Sie haben in der Tat Recht, dass für die Erzwingung von Beziehungen zwischen Datenbanken diese möglicherweise in der Anwendung erzwungen werden müssen.
Ich möchte Sie jedoch darauf hinweisen, dass Sie zuerst die Dokumentation der von Ihnen verwendeten Datenbanksoftware und die vorhandenen Produktangebote überprüfen sollten. Beispielsweise gibt es Clustering-Angebote zusätzlich zu Postgres und MySQL.
Und selbst wenn Sie am Ende brauchen haben einige Validierung in der Anwendung, wirft das Kind mit dem Badewasser nicht aus . Denn je weniger Sie tun müssen, desto besser geht es Ihnen.
Wenn Sie sich Sorgen über zukünftige Skalierbarkeitsprobleme machen, befürchte ich, dass Ihre Anwendung erhebliche Änderungen erfahren muss, bevor sie trotzdem skaliert werden kann. Als Faustregel gilt, dass Sie jedes Mal, wenn Sie 10-fach wachsen, neu designen müssen. Lassen Sie uns also nicht zu viel Geld darauf verwenden, Skalierbarkeitsprobleme nicht zu antizipieren, und verwenden Sie stattdessen Geld, um tatsächlich den Punkt zu erreichen, an dem Sie diese Probleme haben.
Ihre Bewerbung ist nicht korrekt genug.
Wie groß ist die Wahrscheinlichkeit, dass die von Ihnen verwendete Datenbank die Prüfung fehlerhaft implementiert hat, im Vergleich zu der Wahrscheinlichkeit, dass Ihre Anwendung die Prüfung fehlerhaft implementiert hat?
Und welches ändern Sie am häufigsten?
Ich würde wetten, dass die Datenbank jederzeit korrekt ist .
Ihre Entwickler denken nicht genug verteilt.
Rote Fahne ! 1
Wenn Sie denken:
dann du versagt die grundlegendsten Concurrency Problem: ein anderer Prozess / Thread kann den Datensatz werden , indem , wie Sie gehen.
Wenn Sie denken:
Dann haben Sie MVCC nicht berücksichtigt: Die Ansicht der Datenbank, die Sie haben, ist eine Momentaufnahme, als Ihre Transaktion gestartet wurde. Es werden nicht alle Updates angezeigt, die ausgeführt werden, und möglicherweise werden sie nicht einmal festgeschrieben.
Das Aufrechterhalten von Einschränkungen über mehrere Sitzungen hinweg ist ein wirklich schweres Problem. Seien Sie froh, dass es in Ihrer Datenbank gelöst ist.
1 Sofern Ihre Datenbank die Serializable-Eigenschaft nicht ordnungsgemäß implementiert. aber nur wenige tun es tatsächlich.
Zuletzt:
Analysieren Sie keine Fehlermeldungen . Wenn Sie eine Datenbank mit Produktionsqualität verwenden, sollte diese strukturierte Fehler zurückgeben. Sie werden zumindest einen Fehlercode haben, um anzuzeigen, was möglicherweise falsch ist, und basierend auf diesem Code können Sie eine geeignete Fehlermeldung erstellen.
Beachten Sie, dass der Code in den meisten Fällen ausreicht: Wenn Sie einen Fehlercode haben, der besagt, dass ein referenzierter Fremdschlüssel nicht vorhanden ist, ist es wahrscheinlich, dass diese Tabelle nur einen Fremdschlüssel enthält, sodass Sie im Code wissen, um welches Problem es sich handelt .
Und, um ehrlich zu sein, meistens werden Sie Fehler sowieso nicht so anmutig handhaben. Nur weil es so viele davon gibt und du nicht für alle verantwortlich bist ...
... was nur mit dem obigen Korrektheitspunkt zusammenhängt . Jedes Mal, wenn ein "500: Internal Server Error" angezeigt wird, weil eine Datenbankeinschränkung ausgelöst wurde und nicht verarbeitet wurde, bedeutet dies, dass die Datenbank Sie gespeichert hat, da Sie nur vergessen haben, sie im Code zu verarbeiten.
quelle
Dies ist ein zutiefst fehlgeleiteter Punkt. Genau zu diesem Zweck wurden Datenbanken erstellt. Wenn Sie Datenintegritätsprüfungen benötigen (und wenn Sie glauben, dass Sie diese nicht benötigen, irren Sie sich wahrscheinlich), ist es mit ziemlicher Sicherheit effizienter und weniger fehleranfällig, wenn die Datenbank sie verarbeitet, als dies in der Anwendungslogik der Fall ist.
quelle
Die Einschränkungen sollten in Ihrer Datenbank liegen, da (mit dem besten Willen der Welt) Ihre Anwendung nicht die einzige sein wird, die jemals auf diese Datenbank zugreift.
Irgendwann muss möglicherweise ein Skript in der Datenbank installiert werden, oder Sie müssen möglicherweise Daten bei der Bereitstellung von einer Tabelle in eine andere migrieren.
Darüber hinaus können Sie weitere Anforderungen haben, z. B. "Großkunde X benötigt dieses Excel-Datenblatt, das heute Nachmittag in unsere Anwendungsdatenbank importiert wird". Hier haben Sie nicht den Luxus, Ihren Anwendungscode an die Anforderungen eines unsauberen SQL-Skripts anzupassen rechtzeitig.
Hier spart die Integrität auf Datenbankebene Ihren Speck.
Stellen Sie sich außerdem den Entwickler vor, der Ihre Rolle bei diesem Unternehmen übernimmt, nachdem Sie das Unternehmen verlassen haben, und der dann damit beauftragt ist, Datenbankänderungen vorzunehmen.
Hasst er Sie, wenn die Datenbank keine FK-Einschränkungen enthält, damit er erkennen kann, welche Beziehungen eine Tabelle hat, bevor er sie ändert? ( Hinweis, die Antwort ist ja )
quelle
Sie sollten Beziehungen in der Datenbank haben.
Wie die anderen Antwortnotizen zeigen, ist die Leistung der Einschränkungsprüfung in dieser Datenbank weitaus besser als in Ihrer Anwendung. Datenbankeinschränkungsprüfungen sind eines der Dinge, in denen Datenbanken gut sind.
Wenn Sie jemals zusätzliche Flexibilität benötigen, z. B. Ihre notierten Querverweise auf Datenbanken, können Sie die Einschränkungen absichtlich und unter Berücksichtigung entfernen. Konsistenz in Ihrer Datenbank bedeutet, dass Sie die Möglichkeit haben, diese Einschränkungen zu ändern und die Sicherheit der referenziellen Integrität zu gewährleisten.
quelle
Können Sie es sich wirklich leisten, Code für die Durchsetzung der referenziellen Integrität zu schreiben und zu testen, wenn Sie Probleme beim Lösen des zu schreibenden Codes haben?
quelle
Wenn Sie Ihre Datenintegrität, Einschränkungen, Beziehungen usw. nicht auf Datenbankebene validieren, ist es für Benutzer mit Produktionsdatenbankzugriff (über einen anderen Client, einschließlich eines DB-Zugriffstools) viel einfacher, Ihre Daten durcheinander zu bringen.
Es ist empfehlenswert, die Datenintegrität auf Datenbankebene so streng wie möglich zu gewährleisten. Vertrauen Sie mir, dies erspart Ihnen im Laufe der Zeit enorme Kopfschmerzen in jedem nicht trivialen System. Sie werden auch Anwendungslogikfehler oder Fehler und Inkonsistenzen bei Geschäftsanforderungen schneller erkennen, wenn Sie sorgfältig darüber nachdenken.
Gestalten Sie Ihre Datenbank so normal und atomar wie möglich. Keine "Gott" -Tabellen. Entwerfen Sie Ihre Datenbank mit viel Aufwand so einfach wie möglich, idealerweise mit vielen kleinen Tabellen, die individuell sehr gut definiert sind, eine einzige Verantwortung tragen und in allen Spalten sorgfältig validiert wurden. Die Datenbank ist der letzte Hüter Ihrer Datenintegrität. Es repräsentiert den Bergfried der Burg.
quelle
Die meisten Leute sagen im Wesentlichen : „Ja, im Allgemeinen ich soll immer die Beziehungen in der Datenbank definieren“. Aber wenn die Disziplinen der Informatik so einfach wären, würden wir "Software Manual Readers" anstelle von "Software Engineers" heißen. Ich stimme tatsächlich zu, dass die Einschränkungen in die Datenbank aufgenommen werden sollten, es sei denn , es gibt einen guten Grund, warum dies nicht der Fall ist. Lassen Sie mich daher einige Gründe nennen, die in bestimmten Situationen als gut angesehen werden könnten :
Doppelter Code
Manchmal ist im Anwendungscode natürlich eine bestimmte Menge an Funktionen enthalten, die von der Datenbank verarbeitet werden können. Wenn das Hinzufügen von Einschränkungen zur Datenbank überflüssig wäre, ist es möglicherweise besser, die Funktionalität nicht zu duplizieren, da Sie gegen die DRY-Prinzipien verstoßen und die Synchronisierung von Datenbank und Anwendungscode verschlimmern.
Anstrengung
Wenn Ihre Datenbank bereits das tut, was sie benötigt, ohne erweiterte Funktionen zu verwenden, möchten Sie möglicherweise abwägen, wo Sie Zeit, Geld und Aufwand investieren sollten. Wenn das Hinzufügen von Einschränkungen einen katastrophalen Ausfall verhindern und damit Ihrem Unternehmen viel Geld sparen würde, dann ist es wahrscheinlich die Mühe wert. Wenn Sie Einschränkungen hinzufügen, die gelten sollten, von denen jedoch garantiert wird, dass sie niemals verletzt werden, verschwenden Sie Zeit und verschmutzen Ihre Codebasis. Garantiert ist hier das maßgebliche Wort.
Effizienz
Dies ist normalerweise kein guter Grund, aber in einigen Fällen besteht möglicherweise eine bestimmte Leistungsanforderung. Wenn der Anwendungscode eine bestimmte Funktionalität schneller als die Datenbank implementieren kann und Sie die zusätzliche Leistung benötigen, müssen Sie die Funktion möglicherweise im Anwendungscode implementieren.
Steuerung
Etwas im Zusammenhang mit der Effizienz. Manchmal müssen Sie die Implementierung einer Funktion sehr genau steuern, und manchmal muss die Datenbank sie hinter einer Blackbox verstecken, die Sie öffnen müssen.
Schlusspunkte
Das Letzte, was ich sagen werde, ist, dass Sie wissen, ob Sie die Funktionalität nicht in die Datenbank stellen sollten. Wenn Sie sich nicht sicher sind, sind Sie wahrscheinlich besser dran, wenn Sie die Datenbankfunktionen verwenden, da diese normalerweise sehr gut funktionieren.
quelle
Wie immer gibt es viele Antworten. Für mich habe ich eine einfache Regel gefunden (nun, es funktioniert nur für einen modellzentrierten Ansatz). Normalerweise konzentriere ich mich nur auf die verschiedenen Anwendungsebenen.
Wenn das Modell aus mehreren Entitäten besteht und Abhängigkeiten zwischen den Entitäten bestehen, sollte die Persistenzschicht diese Abhängigkeiten mit ihren Möglichkeiten widerspiegeln. Wenn Sie also ein RDBMS verwenden, sollten Sie auch Fremdschlüssel verwenden. Der Grund ist einfach. Auf diese Weise sind die Daten strukturell immer gültig.
Jede Instanz, die an dieser Persistenzschicht arbeitet, kann sich darauf verlassen. Ich gehe davon aus, dass Sie diese Ebene über die Schnittstelle (Service) einkapseln. Hier endet also das Design und die reale Welt beginnt.
Betrachten Sie Ihre Punkte, insbesondere datenbankübergreifende Verweise . In diesem Fall sollte ja keine Referenz im RDBMS selbst implementiert sein, sondern im Service. Aber bevor Sie diesen Weg beschreiten, wäre es nicht besser, dies bereits während des Entwurfs zu berücksichtigen?
Bedeutet, wenn ich bereits weiß, dass es Teile gibt, die in einer anderen DB gespeichert werden müssen, dann kann ich sie bereits dort ablegen und als separates Modell definieren. Richtig?
Sie weisen auch darauf hin, dass die Implementierung in Code flexibler ist . Richtig, aber hört sich das nicht so an, als hätten Sie es mit einem unvollständigen Design zu tun? Fragen Sie sich, warum Sie mehr Flexibilität benötigen?
Das Leistungsproblem ist aufgrund der Integritätsprüfungen in der DB nicht real. Das RDBMS kann solche Dinge viel schneller prüfen als jede Implementierung von Ihnen. Warum? Nun, Sie müssen mit der Medienstörung fertig werden, das RDBMS nicht. Und es kann solche Überprüfungen optimieren, indem es auch seine Statistiken verwendet
Sie sehen, es kommt alles auf das Design zurück. Natürlich können Sie jetzt sagen, aber was ist, wenn eine unbekannte Anforderung auftritt, ein Game Changer? Ja, es könnte passieren, aber solche Änderungen sollten auch entworfen und geplant werden. ;O)
quelle
Sie haben einige sehr gute Antworten, aber noch einige Punkte
Datenintegrität ist das, wofür eine Datenbank entwickelt wurde
Eine ordnungsgemäße Parallelität wie ein FK-Löschvorgang auf Anwendungsebene wäre schrecklich
Kompetenz in Datenintegrität liegt bei einem DBA
Auf der Programmebene fügen Sie ein, aktualisieren, aktualisieren die Massen, fügen die Massen ein, löschen die Massen ...
Thin Client, Thick Client, Mobile Client ....
Die Datenintegrität ist nicht das Fachwissen eines Programmierers - viele doppelte Codes und jemand wird durcheinander bringen es auf
Angenommen, Sie werden gehackt - Sie sind in jeder Hinsicht in Schwierigkeiten, aber ein Hacker kann über ein kleines Loch viel Schaden anrichten, wenn kein Integritätsschutz in der Datenbank vorhanden ist
Möglicherweise müssen Sie Daten direkt über SQL oder TSQL bearbeiten.
Niemand wird sich an alle Datenregeln erinnern
quelle
Ihre Frage macht keinen Sinn: Wenn Sie die Datenbank ändern können, ist es Code. Wenn Sie die Datenbank nicht ändern können, müssen Sie Ihre Einschränkungen an anderer Stelle erstellen.
Eine Datenbank, die Sie ändern können, ist genauso viel Code wie jede Zeile aus Ruby, Javascript, C # oder Ada.
Die Frage, wo eine Einschränkung in Ihrem System erfolgen soll, sollte sich auf Zuverlässigkeit, Kosten und einfache Entwicklung beschränken.
quelle
Hier gibt es jede Menge gute Antworten. Wenn Sie eine App in der Sprache Y haben, können Sie datenbankabhängigen Code in Y erstellen. Wenn dann jemand mit der Sprache Z auf Ihre Datenbank zugreifen möchte, müssen Sie denselben Code erneut schreiben. Gott helfe dir, wenn die Implementierungen nicht genau gleich sind. Oder wenn ein erfahrener Geschäftsbenutzer über Microsoft Access eine Verbindung zu Ihrer Datenbank herstellt.
Meine Erfahrung zeigt, dass Menschen, die keine Datenbankeinschränkungen verwenden möchten, tatsächlich versuchen, etwas Falsches zu tun. Sie versuchen beispielsweise, Daten in großen Mengen zu laden, und möchten für eine Weile Spalten, die nicht null sind, leer lassen. Sie beabsichtigen, "das später zu beheben", da die Situation, die die Nicht-Null-Einschränkung kritisch machte, "in diesem Fall unmöglich passieren kann". Ein weiteres Beispiel ist der Versuch, zwei verschiedene Datentypen in dieselbe Tabelle aufzunehmen.
Erfahrene Leute werden einen Schritt zurücktreten und eine Lösung finden, bei der nicht versucht wird, eine Einschränkung zu umgehen. Die Lösung könnte einfach sein, dass die Einschränkung nicht mehr richtig ist, weil sich das Geschäft natürlich geändert hat.
quelle