Datenbankschema, das spezialisierte Eigenschaften unterstützen kann

8

Ich muss eine Menge von Entitäten speichern, von denen es mehrere spezialisierte Versionen gibt. Sie haben einige gemeinsame Eigenschaften, aber die spezialisierten Eigenschaften enthalten spezifische Eigenschaften für diese Entität.

Lösungen

Der Datenspeicher ist ein relationales DBMS, und dies ist nicht zur Diskussion :-) Insbesondere ist es der Microsoft SQL Server 2005.

Ich könnte leicht eine Tabelle für die allgemeinen Eigenschaften und dann eine Tabelle für jede der spezialisierten Versionen erstellen. Es ist jedoch wahrscheinlich, dass neue Entitäten später zu der Lösung hinzugefügt werden müssen, und ich möchte sowohl ein Objektmodell als auch ein Datenbankschema beibehalten.

Eine andere Idee ist das Erstellen einer Tabelle

%Vor%

und das Feld extended_properties muss eine Art der Serialisierung der erweiterten Eigenschaften sein. Ich dachte entweder JSON oder XML. Ich werde höchstwahrscheinlich einen ORM-Rahmen verwenden, aber ich habe mich noch nicht entschieden. In jedem Fall könnte die Objektdarstellung einer spezialisierten Entität von reading ein Wörterbuch {extended_property_name, value} enthalten, das die analysierten Schlüssel / Wert-Paare aus dem Feld extended_properties enthält.

Von diesem Ссылка sammle ich diese XML-Felder, kombiniert mit Schemas Geben Sie für diese das Konzept von typisiertem XML in das DBMS ein. Auch Abfragen, die den XML-Inhalt im Feld extended_properties enthalten, können diese ebenfalls berücksichtigen.

Was ich will

Feedback zu meinen Lösungsvorschlägen, vor allem dem mit der Tabelle reading und der Serialisierung der erweiterten Eigenschaften.

Außerdem ist mir klar, dass dies eine der Einschränkungen von relationalen DBMS im Vergleich zu Schlüssel / Wert-basierten Speichern ist. Allerdings muss es sicherlich einige Modellierungstechniken geben, um dies zu berücksichtigen.

Jede Rückmeldung wird sehr geschätzt!

    
Anders 29.11.2010, 13:31
quelle

5 Antworten

13

Anders, geben Sie keine Integrität oder Härte auf, z. B. Typ Sicherheit.

(Antwort kommt).

@Anders. Nein, gar nicht, Subtyping ist in Ordnung (die Frage ist, welche Form Sie verwenden und was die Vorteile sind). Gib keine Stärke oder Integrität auf oder gib Sicherheit oder Schecks oder DRI ein. Das Formular, das Sie auswählen, erfordert zusätzliche Prüfungen und möglicherweise ein wenig Code (abhängig von Ihrer Plattform).

Dieses Thema kommt häufig auf, aber der Sucher hat immer eine enge Perspektive; Ich mache immer die gleichen Aussagen (eine Teilmenge) aus einer unveränderlichen Menge. Die Idee ist, alle Optionen zu bewerten. Also ich schreibe ein Dokument. Leider dauert es länger. Vielleicht 4 Seiten. Nicht bereit zum Posten. Aber die Diagramme sind fertig, ich denke du bist am Ball und kannst es sofort benutzen.

Warnung: Nur erfahrene Bauingenieure im Baugewerbe
Straßen sind nicht für Wohnwagen oder Leser mit hohem Eek-Faktor geeignet

Link zu ▶ Vier alternative Datenmodelle ◀ im Dokument Im Aufbau. Entschuldigung für das Chaos auf dem Boden; Ich werde bald aufräumen.

▶ Link zu IDEF1X Notation ◀ für jeden, der mit dem Standard für die Modellierung relationaler Datenbanken nicht vertraut ist.

  1. Sie sind alle relational, mit voller Integrität.

  2. Die 6NF-Optionen. Relational heute (SQL) bietet keine Unterstützung für 6NF; es ist nicht verboten, es stellt einfach nicht die 5NF ➔ 6NF Strukturen zur Verfügung. Daher müssen Sie einen kleinen Katalog erstellen, den manche Leute "Metadaten" nennen. Wirklich, es ist nur eine Erweiterung des Standard-SQL-Katalogs (sys-Tabellen). Die erforderliche Kontrollebene wird in jeder Option modelliert.

  3. Im Wesentlichen EAV richtig gemacht, mit voller Kontrolle und Integrität (Typ Sicherheit, Deklarative referentielle Integrität, etc) anstatt die Unordnung, die es normalerweise ist.

Sie könnten an diesen verwandten Fragen / Antworten interessiert sein (sehen Sie sich insbesondere die Datenmodelle an):

Mehrere feste vs abstrakte flexible

Datenbankschema-Problem

"Simple" Database Design Problem

Antwort auf Kommentare

  

... Auf diese Weise können wir einfach "Kommentar" -Reihen abrufen, die einer bestimmten Instanz eines spezialisierten Typs zugeordnet sind. Ist das der Weg, oder werde ich diese Entscheidung später bereuen? Gibt es ein anderes Muster, das wir vermissen?

Nicht sicher, was du meinst. Kommentare, Notizen, Adressen, die am Ende in vielen Tabellen verwendet werden (Spalten in), so ist die richtige Methode, sie zu normalisieren; eine Tabelle für den Kommentar bereitstellen; Das wird von jeder Tabelle referenziert, die es erfordert. Hier ist eine generische Kommentartabelle. Es wird im Produkt (Supertyp) verwendet, weil Sie any Produkt angegeben haben. Es kann genauso gut in einigen der Produktuntertypen und nicht in anderen verwendet werden. In diesem Fall befindet sich der FK in den genannten Produktsubtypen.

Ihr Datenmodell

>
  

Was ist der Zweck der ProductType-Tabelle in Ihrem Produkt 5NF / Subtyp Beispiel? Enthält es eine Zeile, die jedem spezialisierten Produkt entspricht, z. B. ProductCPU? Ich nehme an, es gibt an, auf welche Spezialisierung sich das Basisprodukt bezieht.

(Kleiner kritischer Fehler im Diagramm, korrigiert.)

Ja, genau.

In Standard-relationalen Begriffen (nicht die unkontrollierten Fehler, die als Datenbanken ausgegeben werden) ist der ProductType der Diskriminator ; Er identifiziert, welche der Produktuntertypen für dieses Produkt gelten. Gibt an, mit welcher Tabelle des Produktuntertyps Sie sich verbinden müssen. Das Paar zusammen ergibt ein logisches Produkt. Vergessen Sie nicht, die Views zu erstellen, eine für jeden ProductType.

  • (Überprüfen Sie, wie sich ProductType für jedes der vier Datenmodelle ändert, welche Rolle es spielt.)

  • "Generalisierung-Spezialisierung" ist alles Hokuspokus, OO-Terminologie; ohne die Grenze zu überschreiten und zu erfahren, wozu Relational seit 30 Jahren fähig ist. Wenn Sie etwas über Relationales lernen, werden Sie die volle Macht haben; ansonsten sind Sie auf den sehr begrenzten OO-Ansatz für alles beschränkt (Ambler und Fowler haben eine Menge zu verantworten). Bitte lesen Sie dieser Beitrag , von 11 Dez 10 ab relationales Datenbankmodell Entitäten, keine Objekte, keine Klassen.

  

Wenn Sie zum Beispiel ein neues Produkt hinzufügen, möchten Sie beispielsweise eine Dropdown-Liste angeben, welche Produkttypen hinzugefügt werden können. Aus dieser Auswahl kann abgeleitet werden, in welche Tabellen die Daten eingefügt werden sollen. Richtig? Es tut mir leid, dass ich über den Anwendungscode gesprochen habe, aber ich muss es nur relativieren

Ja. Und welche Seite (mit Feldern) wird als nächstes bereitgestellt, damit der Benutzer Daten eingeben kann.

Kein Problem, über den App-Code zu sprechen, der den Rdb benutzt, sie gehen zusammen wie Ehemann und Ehefrau (nicht Ehemann und Sklave).

  • Ordnen Sie für Ihre OO-Klassen die Klassenstruktur dem Rdb zu, sobald Sie mit der Modellierung des Rdb fertig sind, unabhängig von einer App, die sie verwenden wird. Nicht umgekehrt. Und nicht abhängig von einer App.

  • Vergessen Sie "persistieren", es hat viele Probleme (verlorene Updates; beschädigte Datenintegrität; problematische Fehlersuche; massive Konkurrenz; etc). Alle Aktualisierungen des Rdb sollten in Transaktionen, mit ACID-Compliance, seit 30 Jahren verfügbar sein, aber Fowler und Ambler haben noch nichts darüber gelesen. In der Regel bedeutet dies, dass ein gespeicherter Prozess stattfindet.

  

Die Diskriminante ist ein FK zu einer Typ-Tabelle, wie wir sie früher beschrieben haben. Sie gibt an, welcher Untertyp spec dem Basistyp entspricht. Aber was enthält die Diskriminantentabelle im Detail?

Ist das aus dem Datenmodell nicht klar? ProducType CHAR(1) oder (2). Name Char(30) .

  

Ein displayfreundlicher Text, der den Typ für UI-Zwecke angibt,

Ja, unter anderem, wie die Kontrolle, Contraint, usw., Beseitigung der Mehrdeutigkeit beim Codieren oder Reporting.

  

aber enthält es auch den genauen Tabellennamen, der den spezialisierten Typ enthält?

Nein. Das wäre etwas zu physisch, um in Daten platziert zu werden. Nicht erlaubt grundsätzlich.

Aber es ist nicht notwendig.

  

Angenommen, ich interessiere mich für das Produkt mit ID = 1. Es hat eine Diskriminante, die anzeigt, dass es sich um eine Produkt-CPU handelt. Wie würden Sie diese Produkt-CPU aus Ihrem App-Code abrufen?

Das ist einfach, wenn Sie das bereitgestellte Modell verwenden und es (alle Tabellen) als Klassen, richtig usw. implementieren. Das von Ihnen angeforderte Beispiel verwendet keine Ansichten (die für Listen und allgemeinere Verwendung sind). Der Pseudocode wäre:

  • mit dem ProductId (Subtyp unbekannt, daher sollte Ihr kein subtypspezifisches Fenster sein), laden Sie nur den Product supertype
  • basierend auf dem Diskriminator Product.ProductType , setze Indikatoren usw. und lade den entsprechenden Subtyp, einen von ProductCPU; ProductMemory; ProductDisk; ProductTape ; usw.

  • Ich habe gesehen (und stimme nicht zu) OO-Methoden, die alle Subtypen gleichzeitig für den gegebenen ProductId laden: ein Subtyp ist gültig; und der Rest ist ungültig. Der Code muss sich immer noch auf die gültige Klasse für Product basierend auf Product.ProductType beschränken.

Alternativ, z. Wo der Kontext ist, sitzt der Benutzer in einem Subtyp-spezifischen Fenster, z. ProductCPU , mit dieser Klasse eingerichtet und Anforderungen ProductId xxx. Verwenden Sie dann die ProductCPU -Ansicht. Wenn es null Zeilen zurückgibt, existiert es nicht.

  • Möglicherweise gibt es ein ProductDisk xxx, aber kein ProductCPU xxx. Wie Sie damit umgehen, ob Sie angeben, dass es ein Produkt'xxx gibt, aber es ist keine CPU oder nicht, das hängt von den Anforderungen der App ab.

Bei Listen, in denen die App ein Gitter ohne Berücksichtigung von ProductId ausfüllt, verwenden Sie die Ansichten (jeweils eine), um jedes Gitter zu laden. Diese SQL basiert auf dem Join und muss nicht auf ProductType verweisen.

    
PerformanceDBA 05.12.2010, 14:14
quelle
1

Ich würde für die Methode "Erstellen Sie eine Tabelle für die allgemeinen Eigenschaften und dann eine Tabelle für jede der spezialisierten Versionen" persönlich gehen.

Grund: Sie sagen, dass Ihre Implementierung in einem RDBMS erfolgt und dies nicht verhandelbar ist. Fein. Ein unstrukturiertes, blobartiges Zeug wie eine serialisierte Hashtabelle in einem DB-Feld auszugeben, widerspricht jedoch der Designphilosophie von RDBMS, so dass die Effizienz stark beeinträchtigt wird, es sei denn, Sie sind damit einverstanden, das Feld * extended_properties * als undurchsichtig zu behandeln Blob, genau wie ein GIF oder ein anderes binäres Objekt.

Mit anderen Worten, vergessen Sie, effizient nach "allen Objekten mit erweiterter Eigenschaft COLOR = RED" zu suchen.

Das Problem, das Sie haben (OO-Taxonomien in einem RDBMS zu beschreiben), ist definitiv nicht neu. Werfen Sie einen Blick auf , um eine ausführliche Beschreibung der Optionen zu erhalten.

    
p.marino 29.11.2010 14:20
quelle
1

Dies ist ein klassisches Beispiel für das Gen-Spec-Designmuster. Gen-spec wird in jedem Tutorial zur Objektmodellierung behandelt, da es durch Vererbung behandelt wird. Es wird häufig in Tutorials zur relationalen Datenmodellierung übersprungen. Aber es ist gut verstanden.

Machen Sie einen Webaufruf über "relationale Modellierung der Generalisierungsspezialisierung". Sie sehen mehrere Artikel darüber, wie Sie eine einzelne Tabelle für die allgemeine Klasse und eine Tabelle für jede spezialisierte Klasse einrichten. Die Artikel helfen Ihnen bei der Gestaltung von Fremdschlüsseln. Insbesondere der Primärschlüssel jeder spezialisierten Tabelle hat eine doppelte Aufgabe. Es ist auch ein Fremdschlüssel für den verallgemeinerten Tisch.

Dies wird Ihnen nicht sehr bekannt vorkommen, wenn Sie Objektmodellierung gewohnt sind. Aber Sie werden feststellen, dass es gut funktioniert. Und die Lösung, die von den meisten Artikeln angeboten wird, ist nicht dynamisch, also müssen Sie jedes Mal, wenn eine neue spezialisierte Unterklasse entdeckt wird, einige DDLs machen.

    
Walter Mitty 29.11.2010 22:00
quelle
0

Hier sind fünf Beispiele aus der SO. Welcher zu verwenden ist, hängt von dem tatsächlichen Problem, das Sie lösen, und Ihrer Präferenz ab.

Im Allgemeinen würde ich davon abraten, Daten in DB-Felder zu serialisieren.

Wenn es relativ wenige spezialisierte Versionen einer Entität gibt, können Sie einfach die Sub-Typisierung wie in diesen Beispielen verwenden: Beispiel eins , Beispiel zwei .

Bei großen Werten von Eigenschaften oder wenn die Eigenschaften dynamisch definiert werden sollen (keine Schemaänderungen), sehen Sie sich eine Implementierung des Beobachtungsmusters wie in diesen Beispielen an: Beispiel drei , Beispiel vier ; oder in die sogenannte 6. Normalform wie beschrieben in: Beispiel fünf . Beachten Sie, dass das "Beobachtungsmuster" eine vereinfachte Version des 6. NF ist.

    
Damir Sudarevic 29.11.2010 16:15
quelle
-1

Diese Technik kann einige Probleme mit dem richtigen Design und der richtigen Leistung haben, aber Sie scheinen einen Kompromiss mit Flexibilität zu benötigen.

Anstatt für jede Eigenschaft spezifische Tabellen oder sogar ein neues Feld zu erstellen, könnte eine Tabelle (und sie wird ziemlich groß sein) für eindeutige Eigenschaften vorhanden sein:

%Vor%

Beispiel: Ein Gebrauchtwagenhändler, der Add-Ons für verschiedene Marken und Modelle verfolgen muss (Sie wissen nie, was sie bekommen werden). Ein paar Datensätze können wie folgt aussehen:

%Vor%

Jeder Wert für jedes Set | Eigenschaftstyp hätte seinen eigenen Datensatz.

Ein weiteres Problem ist, wenn Sie möchten, dass jede Eigenschaft als eine Spalte dargestellt wird, müssen Sie diese Tabelle transponieren.

    
JeffO 29.11.2010 14:44
quelle