Ist es eine schlechte Praxis, mehrere sich gegenseitig ausschließende Eins-zu-Eins-Beziehungen zu haben?

38

Sprich, ein Tisch carhat eine Eins-zu-Eins - Beziehung zu Tabellen electric_car, gas_carund hybrid_car. Wenn a carist electric_car, kann es nicht mehr in gas_caroder a hybrid_carusw. erscheinen.

Stimmt etwas mit einem solchen Design nicht? Einige Probleme, die später auftreten können?

Arthur Tarasov
quelle

Antworten:

59

Die verschiedenen Fahrzeugtypen sind ein Beispiel für ein allgemeines Problem, das bei der Datenmodellierung immer wieder auftritt. Es heißt "Generalisierung / Spezialisierung" in der ER-Modellierung und "Oberklasse / Unterklasse" in der Objektmodellierung.

Ein Objektmodellierer verwendet die im Objektmodell integrierten Vererbungsfunktionen, um das Problem ganz einfach zu lösen. Die Unterklassen erweitern einfach die Oberklasse.

Der relationale Modellierer ist mit einem Problem konfrontiert. Wie werden die Tabellen entworfen, um die Vorteile der Vererbung nachzuahmen?

Die einfachste Technik nennt sich Vererbung einzelner Tabellen . Daten zu allen Fahrzeugtypen werden in einer einzigen Tabelle für Fahrzeuge zusammengefasst. Es gibt eine Spalte, car_type, in der alle Autos eines Typs zusammengefasst sind. Kein Auto kann mehr als einem Typ angehören. Wenn eine Spalte beispielsweise für Elektroautos irrelevant ist, bleibt sie in den Zeilen, die sich auf Elektroautos beziehen, NULL .

Diese einfache Lösung eignet sich gut für kleinere und einfachere Fälle. Das Vorhandensein vieler NULL-Werte erhöht den Speicheraufwand geringfügig und den Abrufaufwand geringfügig. Der Entwickler muss möglicherweise die dreiwertige SQL-Logik lernen, wenn boolesche Tests für nullfähige Spalten durchgeführt werden. Das kann zunächst verwirrend sein, aber man gewöhnt sich daran.

Es gibt eine andere Technik, die als Klassentabellenvererbung bezeichnet wird . In diesem Design gibt es separate Tabellen für gas_car, electric_car und hybrid_car sowie für alle eine kombinierte Tabelle car. Wenn Sie alle Daten zu einem bestimmten Fahrzeugtyp benötigen, verbinden Sie die Fahrzeugtabelle mit der entsprechenden Spezialtabelle. In diesem Entwurf gibt es weniger NULL-Werte, aber Sie können mehr beitreten. Diese Technik funktioniert in größeren und komplexeren Fällen besser.

Es gibt eine dritte Technik, die als gemeinsamer Primärschlüssel bezeichnet wird. Diese Technik wird häufig in Verbindung mit der Vererbung von Klassentabellen verwendet. Die Spezialtabellen für die Unterklassen haben als Primärschlüssel eine Kopie des Primärschlüssels des entsprechenden Eintrags in der Fahrzeugtabelle. Diese ID-Spalte kann sowohl als Primärschlüssel als auch als Fremdschlüssel deklariert werden.

Dies erfordert ein wenig zusätzliche Programmierung, wenn neue Autos hinzugefügt werden sollen, aber es macht die Verknüpfungen einfach, leicht und schnell.

Über- und Unterklassen treten in der realen Welt ständig auf. Hab keine Angst. Testen Sie Ihr ursprüngliches Design jedoch auf Leistung. Wenn Ihr erster Versuch einfach und vernünftig ist, können Sie ihn optimieren, um ihn zu beschleunigen.

Walter Mitty
quelle
3
Wow Danke! Das ist genau das, was ich herausfinden wollte. Die Vererbung von Klassentabellen scheint genau das zu sein, was ich brauche. Ich habe meine akzeptierte Antwort für zukünftige Leser geändert, da ich denke, dass sie die Frage vollständig abdeckt und nicht nur meinen Fall.
Arthur Tarasov
6
Hervorragende Antwort hier. Ein Tipp: Dokumentieren Sie diese Entwurfsentscheidungen gründlich. Welchen Weg Sie auch einschlagen, es wird nicht offensichtlich sein, wenn jemand die Datenbankstruktur untersucht. Bei einigen Datenbanken wie Postgres können Sie einen Kommentar mit den Metadaten Ihrer Spalten, Tabellen usw. verknüpfen .
Basil Bourque
Sie gehen nicht auf die Einschränkung ein, dass Elektroautos keine Hybridautos sein dürfen. Dafür brauchen Sie einen separaten Tisch.
Jmoreno
2
Du hast recht. Wenn Sie der Tabelle cars ein Feld car_type hinzufügen, können Sie die Zugehörigkeit von cars zu nur einem Typ auf Kosten der Abweichung von der vollständigen Normalisierung beschränken. Mit einem guten DBMS können Sie eine Prüfbedingung definieren, die verhindert, dass ein Fahrzeug in mehr als eine spezialisierte Tabelle eingegeben wird. Es ist ein gewisser Aufwand, wenn Sie neue Autos hinzufügen.
Walter Mitty
@ WalterMitty, aber ohne car_typeFeld, woher wissen Sie, nach welcher Tabelle Sie beim Abrufen von Daten suchen müssen? Müssen Sie alle drei Tabellen lesen, um zu sehen, welche Daten zu diesem bestimmten carDatensatz vorliegen?
Josh Part
12

Es ist nichts Falsches daran, so viele Entitätsuntertypen in Ihrem Modell zu haben, wie erforderlich sind, um die Realität der Daten widerzuspiegeln, die Sie modellieren möchten. Die Frage ist nicht, ob Untertypen eine schlechte Praxis sind. Das Problem kann sein, ist es ein gutes Modell ?

Was machen Sie in Ihrem Beispiel beispielsweise mit so etwas wie einem Audi A4 eTron - einem Plug-in-Hybrid? Ist das ein "Elektroauto" oder ein "Hybridauto"?

Die andere Frage, die Sie sich stellen müssen, ist, warum Sie überhaupt untertippen. Wie viele verschiedene Prädikate haben Sie in Ihren Untertypen? Werden einige dieser Prädikate zwischen Untertypen geteilt? Die Situation könnte kompliziert werden.

Die Untertypisierung wird im Datenbankdesign nicht für die Klassifizierung verwendet. Sie können mit Codes, Fremdschlüsseln für Codetabellen oder mit Flags klassifizieren. Die Untertypisierung wird verwendet, um unterschiedliche Prädikatsmengen für verschiedene Typen eines interessierenden Objekts zu modellieren. Wenn Sie Untertypen nur zur Klassifizierung verwenden, ist dies eine schlechte Praxis.

Wenn Ihre Subtypen klar und eindeutig unterschiedliche Prädikatsmengen für die Dinge modellieren, die Ihre Datenbank betreffen, ist dies eine sehr gute Vorgehensweise, unabhängig davon, wie viele Subtypen Sie benötigen.

Joel Brown
quelle
Danke, ich hatte Angst, dass ich mir eine Art Falle stelle. Mein Problem ist, dass jeder der Untertypen viele Spalten haben wird. Einige werden sich überschneiden und ich werde sie in eine carTabelle einfügen, aber viele werden und werden nicht in eine Subtyp-Tabelle eingefügt. Zum Beispiel wird es so etwas wie das Speichern elementarer Teile von Autotypen sein. Elektroautomotor kann wie ein 100 Teile, Gasautomotor 75 Teile und ein Hybrid 125 Teile haben. 50 Teile wären gemeinsam und gespeichert in cars, während 50, 25 und 75 werden in wird electric_car, gas_carund hybrid_carTabellen
Arthur Tarasov