• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

Datenbank-Design: Hierarchische Struktur

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.504
Ich sitze hier gerade an einer Datenbank und bin mir etwas unsicher, wie ich sie am besten designe.
[Weiter unten sind ER-Diagramme]

Die zentrale Entität sind die Objekte.
Ein Objekt hat (im Sinne einer 1:n Beziehung) jeweils ein material, ein material specified, ein kind of object und ein kind of object specified
Letztere sind hierarchisch organisiert, d.h. jeweils 1:n
material --> material specified --> kind of object --> kind of object specified
Dazu kommen mehrere Eigenschaften die decoration, color, production, die jeweils zu kind of object specified gehören.
Das ganze sieht dann so aus:


Frage: Kann ich das guten Gewissens so machen? Macht die Zirkularität nicht Probleme?


---

Weiteres Problem
productions, decorations, colors, etc. da hat sich jetzt gezeigt, dass es relativ viel Überlappung gibt. Bei kind of object specified auch.
D.h. bei kind of object specified gibt es z.B. 10 mal "big vessel" für verschiedene kind of objects.
Bei colors (und dem Rest auch) das selbe. Da gibt es z.B. 10 mal "rot" für die verschiedenen kind of objects specifieds. Weil nunmal ein "big vessel" rot sein kann und ein "small vessel΅ auch. Eine "glass door" kann aber z.B. nicht rot sein.
EIne Variante wäre z.B. 1:n ganz normal bis kind of object specified zu machen und für den Rest eine Materialized Path-artige Struktur herzunehmen. Jede color, decoration, etc. hätte dann mehrere (1:n) paths:

Erläuterung zum paths-table:
Der table hat (neben einem PK) einen varchar, wo der pfad abgespeichert wird in der Form:
"material_id / material_specified_id / kind_of_object_id / kind_of_object_specified_id"
also z.B.:
"3/1/5/6"

Könnte ich dann evtl. auch direkt ebenso für kind of object specifieds einführen?
Deutlich einfacher wäre es natürlich, die Doppelungen bei kind of object specified hinzunehmen und diese in eine n:m Beziehung mit production, decoration etc. zu setzen. Allerdings gibt es jetzt aktuell knapp 1000 Einträge in kind of object specified und das ist ziemlich unübersichtlich das zu verwalten, gerade mit den ganzen Doppelungen (ich denke mal so 80% Überschneidung).

Die Variante mit den materialzed paths klingt irgendwie verlockend. Könnte man auch für die Objekte einführen.
Bin mir aber nicht sicher was Aufwand und Pitfalls angeht.
Weitere alternative wäre eine fertiges Funktionalität herzunehmen: Ancestry for Rails.
Problem dabei ist, dass ich dann die "Typsicherheit" verliere, weil materialzed path im eigentlichen Sinne nur "Nodes" ohne besonderen Typ kennt.
 
Zuletzt bearbeitet:

braegler

Aktiver NGBler

Registriert
14 Juli 2013
Beiträge
896
Hallo erstmal.
Ich bin mal so frei uns zerreisse Dein Design :D

Du solltest versuchen das ganze zu normalisieren. (Normalisierung ist immer gut, man muss es ja nicht übertreiben (und z.B. die 5-stellige Postleitzahl in 5 Feldern speichern).
Eine Tabelle befindet sich in der ersten Normalform, wenn die Werte in jedem Feld und in jedem Datensatz atomar sind, d.h. sich nicht mehr in kleinere Einheiten zerlegen lassen.
Eine Tabelle befindet sich in der zweiten Normalform, wenn sie der ersten Normalform entspricht und darüber hinaus jeder Datensatz nur Felder enthält, die sich auf das Objekt beziehen, das durch den Primärschlüssel dargestellt wird.
Eine Tabelle befindet sich in der dritten Normalform, wenn sie der zweiten Normalform entspricht und darüber hinaus alle Felder, die nicht den Primärschlüssel bilden, voneinander unabhängig sind.
Dein Design enthält für jedes Objekt den kompletten Materialpfad.

db_gv1.jpg

--- [2018-05-16 23:05 CEST] Automatisch zusammengeführter Beitrag ---

name: "F33344", material: "holz", material_specified: "buche", kind_of_object: "Schale", kind_of_object_specified: "Trinkschale", production: "Drehteller", decoration: "Schnitzereien", color: 'mittelbraun"
Nun zur Problematik, dass nicht jedes Objekt aus jedem Material sein kann.
Hier gibt es 2 Möglichkeiten, Black oder Whitelisting und verschiedene Punkte um anzusetzen.
Eine Trinkschale kann nicht aus Papier sein, eine Schale (also das logische Parent) kann jedoch Kinder aus Papier haben (eine kunstvolle Oregamie-Büroklammer-Schale zum Beispiel).
Ich würde an dieser Stelle programmiertechnisch gegenhalten, nicht zwingend mit der Datenbank-Struktur (also Du sagst dem User das die Trinkschale nicht aus Papier sein darf und nicht eine hässliche Fehlermeldung des Datenbankservers).
Whitelist (extended):
whitelist_ID
koos_id
ms_id

Wenn koos_id in Whitelist vorhanden, werden nur die hinterlegten ms_ids erlaubt (also z.B. im Dropdown angezeigt und beim speichern zuvor auf Gültigkeit geprüft)
Ist die koos_id nicht in der Whitelist, werden alle ms_ids legetimiert.
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.504
  • Thread Starter Thread Starter
  • #3
Hi, vielen Dank für dein Feedback, auch in Hinblick auf den Telegram-Chat gestern Abend.
Mir leuchtet das aktuell nicht ein:
Whitelist (extended):
whitelist_ID
koos_id
ms_id
Das scheint mir im wesentlichen ein join-table für eine m:n Beziehung zu sein, nur das koos_id und ms_id eben nicht als Fremdschlüssel benannt werden. Dadurch habe ich aber doch 1:1 die selben potenziellen Probleme, wie wenn ich einfach eine normale relation zwischen koos und material_specified aufbaue, oder nicht? Es können doch die selben Anomalien/Inkonsistenzen auftreten, die ich genau so 1:1 abfangen müsste. Oder sehe ich das falsch? Eher noch mehr, weil die Datenbank in diesem Fall die Integrität auf keinen Fall in irgendeiner Weise sicher stellen kann.

Normalformen sind mir natürlich bekannt, kannst du konkreter sagen, wo du da Probleme siehst?
Die tables haben alle jeweils nur die Attribute "id", "name" + eben ggf. Fremdschlüssel.
Die zitierte Definition zu den Normalformen ist meines Erachtens nach falsch:
Bezüglich der Primärschlüssel muss es heißen: "bilden könnten" und nicht "bilden", also z.B.:
"Eine Tabelle befindet sich in der dritten Normalform, wenn sie der zweiten Normalform entspricht und darüber hinaus alle Felder, die nicht den Primärschlüssel bilden könnten, voneinander unabhängig sind. " Es geht ja immer um Nichtschlüsselattribute und Schlüsselkandidaten, nicht die faktischen Primärschlüssel.
 
Zuletzt bearbeitet:

braegler

Aktiver NGBler

Registriert
14 Juli 2013
Beiträge
896
Hello again.
Die Definition der NF hab ich mir ge-Gutenbergt äh geborgt, aber Du hast natürlich Recht damit.
Bei Deinem initialen Entwurf hattest Du ja den kompletten Materialpfad in Deiner Objekttabelle.
Das heisst, Du könntest (by error) z.B. Holz mit Metall tauschen, und trotzdem das Specified material Buche haben. (ich hab das nur nochmal für Leute geschrieben, die über den Thread stolpern, mit dem erweiterten Design von gestern Abend ist das ja gelöst).

Die whitelist Tabelle ist weitestgehend statisch. Sehe sie eher als eine Art Lookup-Table die in der Preparation-Phase (direkt nach dem Anlegen des KOOS-Eintrags) gefüttert wird (ich kenne den Umfang nicht gut genug um Dir sagen zu können ob eher Black oder White-Listing verwendet werden soll. Hast Du 100 verschiedene Materialien von denen 95 als Trinkschale enden können, bietet sich ein Black-Listing an).

Whitelist:
tbl_whitelist
1 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Stahl
2 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Porzellan
3 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Platin

Soll nun ein Objekt des Typs "Feuerfeste Schale" angelegt werden, prüfst Du ob es in der Whitelist Einträge für ID_der_FeuerfestenSchale gibt.
Wenn ja, werden nur die in der Tabelle vorhandenen ID_von_MaterialSpecified mit ID_der_FeuerfestenSchale ins Formular übernommen. Der User hat also keine Chance hier Papier zu wählen.
Wenn nein, werden alle MaterialSpecified zu Auswahl angeboten.

oder aber auch als Blacklist
tbl_blacklist
1 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Papier
2 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Nitrozellulose
3 : ID_der_FeuerfestenSchale : ID_von_MaterialSpecified_Streichholzköpfchen

Der Benutzer erhält in diesem Falle alle MaterialSpecified ausser jene, die in der Blacklist für ID_der_FeuerfestenSchale gelistet sind.
Beim speichern (man traut ja keinen Userinput) musst Du die Prüfung wiederholen.

Relevante Inkonsistenzen können dabei eigentlich nur vorkommen, wenn sich die FeuerfesteSchale plötzlich zur nichtFeuerfesten verwandelt, dabei aber die KOOS-ID gleich bleibt.
Wenn Du die FeuerfesteSchale aus dem Sortiment nimmst, sind die Einträge in der Black- bzw. Whitelist zwar verwaist, aber das tut der Funktion keinen Abbruch (deshalb wird die ID darin auch roh gespeichert und nicht als Teil einer Relationship damit der DB-Server nicht ins Straucheln gerät)
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.504
  • Thread Starter Thread Starter
  • #5
Danke für deine Erläuterung :).

Das heisst, Du könntest (by error) z.B. Holz mit Metall tauschen, und trotzdem das Specified material Buche haben.
Ja, stimmt schon, allerdings gilt das für das neue Design ja auch, bezogen auf material_specified und kind_of_object_specified. Wenn ich eines ändere, bleibt das andere davon fälschlicherweise unberührt. Das mit der White-Liste (gehen wir von diesem Fall aus, Black-Listing ist ja weitgehend analog) muss ich ja wie du schreibst auf Applikationsebene regeln. Aber wieso dann nicht das alte Design nehmen und die Prüfung über die Relationen machen?
Sprich: Benutzer ändert von Holz auf Metall, dann prüft die Aplikation, ob Buche in "belongs_to" Beziehung mit dem neuen Material Metall steht und gibt sonst eben einen Fehler / eine Warnung aus.
bzw. bei einer 1:n-Beziehung wäre das ja sowieso immer der Fall.
Aber wenn ich kind_of_object und k_o_o_s als m:n modelliere, dann ist mein lookup-table / Whitelist-Table ja einfach der join-table über den das m:n realisiert wird.
 

braegler

Aktiver NGBler

Registriert
14 Juli 2013
Beiträge
896
Wenn ich eines ändere, bleibt das andere davon fälschlicherweise unberührt.
Ist das nicht gewollt? Die bestellte Trinkschale (KOOS) soll nun halt nicht aus Buche sondern Erle (oder Zinn) sein. Nur weil Du das Material des Produktes änderst ändert sich ja nicht der Typ dessen.
Natürlich kannst Du das auch anders abbilden. Am Schluss musst du aber irgendwie listen, aus welchen MS (oder Material, was widerrum das Problem hat, dass eine Trinkschale z.B. nicht unbedingt aus Balsaholz oder Spanplatte sein sollte ) ein Trinkbecher sein darf oder nicht.
Die erste Frage hier wäre für mich daher, auf welcher Ebene Du diese Ausschlusskriterien ansetzt (Material, oder MaterialSpecified).




Alternativ zur Black oder Whitelist, bastelst Du eine Eigenschaft-Tabelle mit den Verträglichkeiten und lagerst die Info in je eine 1:n Tabelle zu KooS und MS aus
db2.jpg
Damit hättest Du die gesamte Sache in der Datenbank in Relation gebracht. Da musst Du dann "nur" sicherstellen, dass das gewählte MS in der ms_rob die identischen Rob_ID (RobParameter) enthält wie das aktuelle KOOS in der koos_rob.



Natürlich könntest Du auch ein Bitmask nutzen um die Material-Widerstandsfähigkeit abzubilden (habs hier mal zum Spass negiert, möglich ist ja nahezu alles )
1 = keine hohen Temperaturen
2 = kein Wasser
4 = keine Oxidationsmittel
8 = keine Lebensmittel
...
...

Dann könntest Du dieses Bitmask als Integer in den MS hinterlegen und beim Anlegen eines KOOS das entsprechende Requirement definieren
MaterialSpec: Bleizinn 13 1001
MaterialSpec: Papier_gebleicht 7 0111
MaterialSpec: Buche 1 0001
KooS : Trinkschale 10 1010

Mögliche Auswahl: where !(MaterialSpecified.Mask & KooS.Mask)
 
Zuletzt bearbeitet:

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.504
  • Thread Starter Thread Starter
  • #7
So, Update/Fazit.
Nachdem ich die Optionen durchgegangen bin, sprich einmal materialized path und die Ansätze von braegler bin ich am Ende bei dem geblieben was mir am Ende das naheliegendste war. Der Trade-Off schien mir in jedem Fall sonst doch zu schlecht zu sein, relativ wenig Gewinn aber sehr viel gebastelt das nach hintenraus viel Arbeit macht.
So sieht es jetzt aus:


Es gibt also vereinfacht dargestellt folgendes. Als Notation für 1:n bzw. n : m nehme ich |a|---<|b| bzw. |a|>---<|b|

|material|---<|material_specified|---<|join_table|>---|kind_of_object_specified|>---|kind_of_object|

An |join_table| werden entsprechend die Eigenschaften angehängt:

|join_table|>---<|color|
|join_table|>---<|decoration|

und so weiter. Da da n : m ist hängt da im ER Diagramm natürlich noch ein weiterer join Table zwischen.
Ich vermeide so jedenfalls redundanz. Das Einhängen der eigenschaften direkt an kind of object specified ging leider nicht wegen der n : m Beziehung mit material specified.
Ein doofes Problem ist, dass es jetzt zu jedem kind of object immer ein kind of object specified geben muss. Was eigentlich nicht der Fall ist. Das verarzte ich auf der Applikationsebene, indem in diesem Fall ein kind of object specified mit dem selben name wie kind of object angelegt wird. Unschön. Ein Datenbank-Architekt würde mich für das Teil vom Hochhaus werfen. Aber in der Gesamtheit habe ich auf jeden Fall jetzt was womit ich gut arbeiten kann.
 
Oben