Fremdschlüssel

13 replies [Letzter Beitrag]
Lenin171
Offline
Joined: 20.12.2007

Hallo zusammen,

habe hier eine grundsätzliche Frage zu Fremdschlüssel.
Bin Entwickler und schreibe diverse Client/server-Applikationen. Die Applikationen greifen grundsätzlich über SP’s auf die DB zu. Egal, ob Selektion, Update usw.
Die Daten sind eher Objekt-orientiert abgelegt, gekapselt in Schemata und eindeutig per id indiziert. Logisches Löschen vermeide ich im laufenden Betrieb, arbeite lieber mit einem Del-Flag(0/1). Aufgeräumt wird 2 oder 3mal im Jahr, reorganisieren und fertig. Dies funktioniert ganz gut. Die Struktur der Daten entspricht einem Schneeflockenschema.

Jetzt frage ich mich, ob ich nicht die Fremdschlüssel zu stark vernachlässige. Denn die richte ich eigentlich nie ein. Da die Daten kontrolliert per SP in die DB kommen, hatte ich auch noch nie Probleme mit der Selektion von Daten über Joins. Die Beziehungen zwischen meinen PrimaryKeys handhabe ich grundsätzlich über meine SP’s.
Ich definiere aber nie Foreign Keys. Auch Checks definiere ich nie. Constrains erst recht nicht, da die Daten stark gekapselt und eindeutig in der jeweiligen Tabelle sind.
Damit fahre ich wirklich sehr gut. Die Schnittstellen zur Applikation sind zentral, durch die SP’s, und die DB’s sind sehr gut wartbar.

Trotzdem, macht es mehr Sinn mit Foreign Keys zu arbeiten? Ist es für den Server besser Foreign Keys definiert zu haben, obwohl die Id einer andren Tabelle eh nur einmalig in der Untertabelle existiert?

Muthmann
Offline
Joined: 20.12.2007

Hallo!
Ein Realname wäre zum antworten ganz schön!

Constraints wie z. B. UNIQUE oder Foreign Key sind eher für die Integrität der Daten da und nicht so sehr für die Performance. Ein Unique-Index gibt dem Optimizer allerdings Hinweise über die Verteilung der Daten. Ein Index über die FK-Spalte unterstützt einen Lookup, wenn z. B. der Parent-Satz gelöscht werden soll.

Grundsätzlich verlasse ich mich beim DB-Design nie auf die Fehlerfreiheit irgendeiner Software und beuge Inkonsistenzen durch entsprechende Constraints vor. Nachteil ist, dass sich die Reihenfolge der Deletes/Inserts an den FK-Constraints orientieren muss.

Einen schönen Tag noch,
Christoph Muthmann
Microsoft SQL Server MVP

Lenin171
Offline
Joined: 20.12.2007

Ich danke Dir. Grüße Robert

admin
Offline
Joined: 19.12.2007

Da du schreibst, aller Zugriff erfolgt über SP's, vermute ich, dass du auch die Rechte auf die Basistabellen entfernt hast, oder? Falls nicht, hast du einen sehr guten Grund, warum du Constraints dort definieren solltest, wo sie niemand umgehen kann. Auf Ebene der Datenbank selber.

Ich stimme Christoph zu, dass ich Clients grundsätzlich nicht traue. Ebensowenig vertraue ich aber auch mir selber, was ein weiterer Grund für die Vielzahl von Constraints ist, die ich in meinen Datenbanken habe. Niemand ist perfekt, so dass schon mal der eine oder andere Check in einer Prozedur vergessen wird.
--
Frank Kalis
Microsoft SQL Server MVP
Webmaster: http://www.insidesql.org

Lenin171
Offline
Joined: 20.12.2007

Hallo Frank,

das glaube ich nicht. Es ist sicher nicht besser, wenn die Daten erst beim schreiben auf ihre Sinnhaftigkeit überprüft und mit zu vielen Referenzen hinterlegt sind. Wie gesagt, es gibt eh nur eine ID zum referenzierten Satz.

Das einzige was die User(Gruppen) dürfen, sind die SP’s ausführen. Die erwarten ja eh die notwendigen Parameter, ist einer Null(der nicht Null sein sollte) wird erst gar nicht geschrieben. Und, ich kann auch noch saubere Fehlermeldungen hochreichen. Keine Aktionen bei fehlerhafte Daten.

Also, niemand hat Berechtigungen auf Tabellen oder Views. Das einzige was man sehen kann sind die SP’s. (Übrigens Views, Matrialisierte leuchten ja noch ein…)

Wie wartet ihr eure Datenbanken? Wenn Du nur ansatzweise einen objektorientierten Ansatz in der Tabellen-Struktur hast, dann sollte dies doch kaum Aufwände bereiten. Weder in der Wartung noch in der Weiterentwicklung.

Wenn ihr wirklich an allen Ecken mit diversen Checks und Constrains arbeitet, dann löst ihr beim Schreiben von etwas mehr verteilten Daten ein wahres Feuerwerk aus. In jeder Tabelle knallt es.

Frank, das glaube ich nicht.

Muthmann
Offline
Joined: 20.12.2007

Hallo Robert,
wie ich oben schon geschrieben habe, muß man einiges beachten, wenn man das Feuerwerk nicht sehen will! Grundsätzlich ist es eine gute Idee, die Daten bereits in der Anwendung zu prüfen. Constraints auf der Datenbank können vor fehlerhaftem Programm-Code schützen, oder vor falschen Zugriffen mit anderen Tools. Die Fehlermeldungen die bei einer Constraint-Verletzung auftreten, solltest Du abfangen und in sinnvoller Form an den Anwender weiterreichen.

Bei uns bedeutet eine Änderung in der Software in der Regel auch immer eine Änderung in der Datenbank. Das ist kein besonderer Aufwand, bedarf aber der Vorbereitung, damit auch alle neuen Constraints angelegt werden können. Nur wenn ich nach einer Änderung alle Constraints angelegt habe, kann ich sicher sein, dass die Datengrundlage in Ordnung ist. Hier helfen die Constraints also auch bei der sauberen Bereitstellung vor Produktionsbeginn der Software.

Einen schönen Tag noch,
Christoph Muthmann
Microsoft SQL Server MVP

admin
Offline
Joined: 19.12.2007

[quote=Lenin171]Hallo Frank,
das glaube ich nicht. Es ist sicher nicht besser, wenn die Daten erst beim schreiben auf ihre Sinnhaftigkeit überprüft und mit zu vielen Referenzen hinterlegt sind. Wie gesagt, es gibt eh nur eine ID zum referenzierten Satz.
[/quote]
Das habe ich auch so nicht gemeint. Richtig ist, dass eine Validierung bereits in der Anwendung vorgenommen werden sollte. Auch richtig ist, dass eine Validierung in der Stored Procedure vorgenommen werden sollte. Aber dann gibt es noch die Ebene der Datenbank Engine, die als "last line of defense" ultimativ die Integrität sicherstellen soll und kann. Schliesslich ist das ihre aufgabe und DBMS Systeme sind daraufhin ausgelegt.
[quote]Wie wartet ihr eure Datenbanken? Wenn Du nur ansatzweise einen objektorientierten Ansatz in der Tabellen-Struktur hast, dann sollte dies doch kaum Aufwände bereiten. Weder in der Wartung noch in der Weiterentwicklung.[/quote]
Mir ist jetzt nicht ganz klar, was du mit "objektorientiertem Ansatz" meinst, aber meine Datenbanken sind so normalisiert wie es nötig ist. Wartung bereitet kaum Aufwand, da die Schemata statisch sind, resp. bei einer Datanbank verfolgen wir einen EAV Ansatz, aber das ist ein anderes Thema. Weiterentwicklung ist ebenfalls kein Thema, wenn sie mit der gebotenen Sorgfalt vorgenommen wird.
[quote]Wenn ihr wirklich an allen Ecken mit diversen Checks und Constrains arbeitet, dann löst ihr beim Schreiben von etwas mehr verteilten Daten ein wahres Feuerwerk aus. In jeder Tabelle knallt es.[/quote]
Eh? Kannst du das etwas näher erläutern?
--
Frank Kalis
Microsoft SQL Server MVP
Webmaster: http://www.insidesql.org

Lenin171
Offline
Joined: 20.12.2007

Christoph danke.
Frank, passt schon.

Lenin171
Offline
Joined: 20.12.2007

Ich lach mich tot! Selbst Microsoft verzichtet auf Fremdschlüssel in der Produktion. Aus dem gleichen Grund, den ich hier als Feuerwerk angedeutet habe.
Die Antwort meiner Frage findet ihr im Webcast "Einführung SQL Server 2008 (Teil 7 von 10): Optimieren von SQL Server 2008 und SQL Server Express 2008 - Ausführungspläne und Optimierungsstrategien"
Habe soeben den Webcast übersprungen und bin doch tatsächlich auf die Antwort gestoßen.

Für die Microsoft SQL Server MVP-Spezialisten: Schaut euch den Webcast ab Minute 37:20 an.

Sogar mein Feuerwerk, lieber "last-line-of-defense- Frank", wird ab der 38. Minute angesprochen.

admin
Offline
Joined: 19.12.2007

Fein, dann ist doch alles klar! Wenn es in einem WebCast von Microsoft erwähnt, muss es ja richtig und definitiv sein!

Wenn du mit deiner Art des Datenbank-Designs zufrieden bist, verstehe ich nicht, warum du hier eine Frage stellst und eine aufkommende Diskussion dann direkt mit einem "Passt schon" wieder im Keim erstickst?
--
Frank Kalis
Microsoft SQL Server MVP
Webmaster: http://www.insidesql.org

Lenin171
Offline
Joined: 20.12.2007

Hallo Frank,
weil mir die Qualität der Antworten nicht gefällt. Christoph seine Antworten lass ich mir noch gefallen und hätte sicher angeknüpft. Aber Deine Antworten gingen gar nicht. Erst recht nicht, wenn Du mir mit Formulierungen wie „Last line of defence“ kommst. Auch der erwähnte EAV Ansatz und der objektorientierte Ansatz. Diese Antworten und die Signatur „Microsoft SQL Server MVP“ haben mich wirklich geärgert. Egal

Eigentlich wollte ich schon nicht mehr antworten. Bin eh fast nie in Foren. Aber, da ich eben meine Bedenken hatte, dachte ich: Schaust Du mal wieder unter insideSQL, evtl. antwortet jemand wie z.B. Andreas Kosch. Auch egal.

Nun, da Du so nett geantwortet hast, will ich gerne den Beitrag auch ordentlich beenden.

Ich habe eigentlich eine simple Frage gestellt. Benötigt man überhaupt Fremdschlüssel, oder vernachlässige ich evtl. etwas. Man schreibt seine Anwendung und deren Datenbanken und sieht evtl. einfachste Sachen nicht mehr.

Initiator war eine Datenbank aus der Produktion. Echt, ich bin fast ausversehen auf das Datenbank-Diagramm gekommen. Kennt sicher jeder von euch. Nach einiger Zeit Rechnerlast, dachte ich schon das kannst Du jetzt vergessen. Nicht dass noch die Management Konsole den Prozess abgibt. Aber siehe da, es ging weiter.
Und dann kam es. Eine Invasion an Tabellen und Verknüpfungen bricht auf mich rein, dass ich … keine Ahnung. Es war einfach unfassbar.
Klar habe ich gleich eine meiner DB’s geöffnet, aber da kam nichts. Nur die Einzelansichten der verschiedenen Tabellen. Echt, das war fast wie ein Schock. Da kommen dir echt merkwürdige Gedanken. Erst recht, wenn die nächste DB Dich auch enttäuscht.

Der nächste Grund war die Intellisense im Management Studio 2008. Bis jetzt habe ich immer mit dem „SQL Assistant“ gearbeitet, da Microsoft dies nie implementiert hatte. Und was soll ich sagen, beim Join bekomme ich doch klatt in der Verseuchten(<- nicht ernst nehmen) die Tabellen als Vorschlag angezeigt. Wahnsinn! Ich dachte ich spinne.
Das Warum ist schon klar…, aber warum nicht in meiner!

Aus diesem Grund habe ich mal kurz meine Vorgehensweise geschildert. Natürlich zu kurz und ungenau. Aber, wenn du Antworten wie „Grundsätzlich verlasse ich mich beim DB-Design nie auf die Fehlerfreiheit irgendeiner Software und beuge Inkonsistenzen durch entsprechende Constraints vor.“ Bekommst, dann weißt Du: Dies war eine nicht so gute Idee.

Ich glaube, dass ihr evtl. etwas mehr übern Rand hinaus schauen solltet. Denn eine DB ist einzig und alleine für die Bereitstellung von Informationen, die grundsätzlich über „irgendeiner Software“ abgerufen, dargestellt und aktualisiert werden. Und dies löst zum Beispiel Microsoft perfekt.

Schaut euch doch mal die Controls einer Applikation an. Einfach mal ein paar Stunden mit beschäftigen. Die Controls sind für diese Art von Informationen gebaut. Die Id eines Datensatzes bleibt die gleiche Id im Control. Das z.B. vachar-Feld aus dem Datensatz ist die Text-Darstellung. Diese kannst Du ändern, doch der Datensatz bleibt der Gleiche, weil die Id beim Speichern wieder nur diesen Datensatz z.B. aktualisiert. Da diese ID der geclusterte Primary Key(Identity) ist, greift die Datenbank eh direkt auf den Speicher zu und z.b. aktualisiert ihn.

Es gibt unterschiedliche Arten von Controls. Aber grundsätzlich unterscheiden Sie sich nur dadurch, dass die Einen die Inhalte ändern können, die Andren die Informationen nur darstellen können. Die Informationen, die nur einer Darstellung oder Kombination unterliegen, verändern ihre Eindeutigkeit innerhalb der DB eh nicht.
Zum Beispiel einen FK auf einen Datensatz der eh nur in einer z.B. ComboBox dargestellt wird, sehe ich nicht.

Es ist nur ein kleines einfaches Beispiel. Versucht es einfach mal. Microsoft hat mit dem neuen Framework ganze Arbeit geleistet.

Ab SQL 2005 hat die DB wirklich an allen Ecken gewonnen. Die Schemata, die echt lange ignoriert wurden oder z.B.try and catch. Alles was mit dem 2008er kommt, sind Verbesserungen in der z.B. Administration oder einige neue Funktionen.
Wichtig sind bei einer DB letztendlich Sachen wie neue Datentypen. Diese sind die eigentlichen Erweiterungen einer Datenbank. Anpassungen an die heutige Zeit, um neue Informationen speichern zu können.

Mein Eindruck ist eher der, dass FK‘s aus Zeiten von Access stammen. Dem visuellen Aufbau von „Daten-Container“. Dies hat aber nichts mit einer DB zutun. Ich glaube auch, das Access einem ungewollten Virus ähnelt, den Microsoft nicht mehr los bekommt.

Diese ganze Verkettungen und Prüfungen. Die Aufhebung von Verkettungen innerhalb der DB, damit man löschen kann … geht ja gar nicht. Die Tabellen sind reine Informationsspeicher. Die SP’s stellen die eigentlichen Schnittstellen einer DB. Und direkte Select’s, Insert’s oder Updates auf eine Tabelle sind echt krank. Das Löschen eines Datensatzes im laufenden Betrieb, grauenhaft! Trigger… will ich gar nicht erst mit anfangen… So quälst du dein Auto ja auch nicht.

Ehrlich, lasst euch nicht zu viel Misst(z.B. Last line of defence) auf den Lehrgängen erzählen. Probiert es einfach mal aus. Schreibt eine kleine Applikation, mit den standard-controls, die Microsoft zur Verfügung stellt. Stellt die Informationen so zusammen, wie sie auch logisch zusammen gehören. Und identifiziert jeden Datensatz mit einer ID. Felder, die ein Benutzer ändern kann, dürfen eh nur reine Informationen zu der ID sein.
Diese Felder spielen immer die zweite Geige und sollten keinen Einfluss auf die Datenstruktur haben. Müller mit Umlaut oder ohne ist egal.
Müller ist die Nummer 198276. Erst recht nicht in Zeiten der Globalisierung. Ist nicht auszumalen, wie der nette Kollege(Franzose-Chinese-Inder) in Deiner Firma Herrn Müller schreiben würde. Den Datensatz findest Du nie wieder.
Die 198276 dagegen schon. Und das auch noch extrem schnell, da sie geclustert ist. Und dann kannst dich auf etwas gefasst machen…

Ich danke euch trotzdem und widme mich wieder der neuen App. Werde immer an dieses Forum denken, wenn die IntelliSense mir mal die Joins vorab selektiert…

Grüße
Robert

admin
Offline
Joined: 19.12.2007

Danke für deine ausführliche Antwort! Falls ich dir irgendwie auf den Schlips getreten sein sollte, entschuldige ich mich dafür.

Diese Argumente höre ich immer wieder von unseren C# & Java Entwicklern. Und ich stimme ganz und gar nicht damit überein. Foreign Keys sind eines der Schlüsselkonzepte des Relationalen Modells und eine Datenbank sollte nur in einem einzigen Fall keine Foreign Keys enthalten: Nämlich dann wenn es keine logische Beziehung zwischen den abgebildeten Entitäten gibt.

...und ehrlich gesagt kann man in einem solchen Fall auch genausogut mit Flat-Files auf einem High-Performance Disk Subsystem arbeiten. Dafür braucht es keine relationale (oder SQL) Datenbank.

Ich habe eine Datenbank in der wir nach 10 Monaten Produktionsbetrieb über 1 Milliarde Transaktionen in einer Child Tabelle durchgeführt haben. Da ich niemals aus der Parent-Tabelle lösche, habe ich mich dafür entschieden, keinen Index für die FK Spalte zu erstellen, wie "üblicherweise" empfohlen wird. Spart eine Menge Zeit und Diskspace. aber den FK selber löschen? Niemals! Bisher hat sich kein Anwender über die Performance beklagt.

Natürlich kosten FK´s Performance. Aber dieses nehme ich gerne in Kauf, wenn ich mich dafür in Gegenzug darauf verlassen kann, dass die Antworten der Datenbank "richtig" sind. Was aber dürfte mehr Performance kosten? Sämtliche Validierungen, Checks, etc... in interpretiertem SQL Code und/oder auch Client-Code zu machen, der erst auf die Datenbank zugreifen muss, oder dies auf der Ebene der Datenbank-Engine zu machen, wo dies in kompiliertem Maschinen-Code erfolgt?

Wenn das Konzept von Foreign Keys (oder auch der anderen Constraints) tatsächlich "überflüssig" sein sollte, warum unterstützen sämtliche grossen Anbieter es immer noch? Schliesslich waren doch fast 40 Jahre Zeit, da mal reinen Tisch zu machen und diesen Ballast von Bord zu werfen. Vielmehr ist eher das Gegenteil der Fall. MySQL hat zum Beispiel ursprünglich Foreign Keys nicht unterstützt. Je mehr dann MySQL auch im Enterprise Bereich Fuss gefasst hat, umso zwingender wurde auch der Druck, FK's zu implementieren und mittlerweile bietet auch MySQL dieses Feature an.

Egal, wie auch immer. Viel Spass mit deiner neuen App!

Muthmann
Offline
Joined: 20.12.2007

Hallo Robert,
ich kann die Ausführungen von Frank nur unterstützen. Übrigens schreibt auch Andreas Kosch in seinem Buch "SQL Server 2005 Programmierhandbuch" ab Seite 165 über "FOREIGN KEY - der Sicherheitsgurt".
http://www.amazon.de/gp/reader/393908400X/ref=sib_rdr_zmin?p=S007&j=1#re...

Schau Dir auch mal die Datenbank der Reporting Services an. Da wimmelt es auch nur so von Fremdschlüsseln.

Einen schönen Tag noch,
Christoph Muthmann
Microsoft SQL Server MVP

Muthmann
Offline
Joined: 20.12.2007

Ich weiß, dass das Thema schon ein paar Monate zurückliegt. Beim lesen dieses blogs kam es mir aber wieder in den Sinn: http://blogs.msdn.com/conor_cunningham_msft/archive/2009/11/12/conor-vs-...

Hieraus ein kleiner Ausschnitt:
So, you should think of Foreign Keys as a great way to give the Optimizer hints to speed up your query, in most cases. The only cases where I recommend that customers NOT define Foreign Keys is in very large data warehouses (which I will save for another blog post).

Also sollten wir FK-Constraints nicht nur im Sinne der Datenintegrität schätzen, sondern auch durch die Möglichkeiten nicht verwendete Teile aus Joins zu eliminieren.