# Beratung für Datenbankdesign



## heart_disease (27. Jul 2011)

Ich bräuchte dringend Beratung beim Entwurf eines Datenbankdesigns.

Ich muss eine Datenbank entwerfen, welche sämtliche Daten zu verschiedenen CNC-Maschinen speichert und auch gegeneinander vergleichen kann. Das Hauptproblem ist allerdings, dass die verschiedenen Entitäten einer Maschine einmal aus Strings, einmal aus Integers oder Floats oder gleich Feldern aus Integers bestehen können. Als noch etwas unbedarfter Datenbankdesigner stehe ich nun vor einem Problem - ich kann ja wohl schlecht alle Entitäten in eine fette Tabelle "machines" stopfen, oder? Meine Überlegung war, für jede Entität die eine Maschine haben kann, eine eigene Tabelle in der Datenbank anzulegen - das wären dann etwa so um die 60 Tabellen. Der Vorteil davon wäre, dass ich so auch ganz gut die deutsche Bezeichnung der Entität (zB Umlaufdurchmesser oder Drehmoment) und die Maßeinheit dazu speichern kann. Allerdings bedeutet das auch einen großen Aufwand - erstens zum Erstellen der vielen Tabellen und zweitens beim Joinen.

Meine Frage wäre nun: ist mein Ansatz ein guter bzw. ist er vlt. sogar der einzig saubere oder bin ich total auf dem Holzweg?


----------



## nillehammer (27. Jul 2011)

Hallo heart_disease,
nur, dass ich die Aufgabe richtig verstehe. Ich versuchs mal mit objektorientierten Begriffen zu beschreiben (bin schließlich Java-Entwickler ). Also, Du hast eine allgemeine Klasse "Maschine" mit einigen wenigen Attributen, die für alle Maschinen gleich sind. Von dieser allgmeinen Klasse gibt es sehr viele spezielle Ausprägungen, die zum Teil sehr unterschiedliche Attribute haben. Hab ich das so richtig verstanden/beschrieben?
Gruß nillehammer


----------



## fastjack (27. Jul 2011)

Ich würde es so probieren:

Eine Tabelle Machine mit einigen wenigen Spalten, die alle Maschinen auch haben können. Die Bedeutung der Spalten würde ich in einer Resourcendatei oder so speichern, die Spalten halt auf Englisch benennen. Und noch eine Spalte MachineType, die auf einen Datensatz in einer Tabelle MachineTyp (der Maschinentyp halt) zeigt und noch eine Spalte MachineRef, die auf den entsprechenden Datensatz in einer der MachineXYZ-Tabelle zeigt.

Pro Maschine eine Tabelle MachineXYZ mit weiteren Spalten, speziell für die Maschine.

edit: Eventuell noch in MachineXYZ eine Spalte Machine, die auf den jeweiligen Machine-Datensatz zeigt.


----------



## homer65 (27. Jul 2011)

Um wieviele Maschinen geht es denn?
Ist die Datenmenge so groß, das es Performanceprobleme geben könnte?

Jedenfalls wäre eine Tabelle mit ca 60 Spalten auch nicht ungewöhnlich. 
Es ginge durchaus alle Attribute in einer Tabelle abzuspeichern.
Du verschwendest etwas Plattenplatz, wenn von den 60 Attributen im Schnitt kleiner 10 belegt sind. Aber, ist das wichtig?


----------



## heart_disease (27. Jul 2011)

nillehammer hat gesagt.:
			
		

> Also, Du hast eine allgemeine Klasse "Maschine" mit einigen wenigen Attributen, die für alle Maschinen gleich sind. Von dieser allgmeinen Klasse gibt es sehr viele spezielle Ausprägungen, die zum Teil sehr unterschiedliche Attribute haben. Hab ich das so richtig verstanden/beschrieben?


Hm, nicht ganz. Es gibt viele Maschinen, welche aber alle diesselben Attribute besitzen (nur mit verschiedenen Werten natürlich). Aber jede Maschine hat ein Drehmoment, eine max. Drehzahl, etc. Das Problem dabei ist jetzt, dass zB das Attribut "Schwenkwinkel B" Werte wie max. und min. Winkel beschreiben, während ein anderes Attribut wieder durch einen String oder eine Folge von Ganzzahlen beschrieben wird. Daher dachte ich daran, dass jedes Attribut eigentlich eine eigene Klasse sein müsste. Außerdem sind die Attribute auch noch in Gruppen unterteilt.

[Gruppe 1](Attribut 1)
   (Attribut 2)
   (Attribut 3)
   (Attribut 4)​[Gruppe 2](Attribut 1)
   (Attribut 2)
   (Attribut 3)​


			
				homer65 hat gesagt.:
			
		

> Es ginge durchaus alle Attribute in einer Tabelle abzuspeichern.
> Du verschwendest etwas Plattenplatz, wenn von den 60 Attributen im Schnitt kleiner 10 belegt sind. Aber, ist das wichtig?


Es ginge mir dabei eher um die Sauber- und Übersichtlichkeit. Ich habe das irgendwie so im Kopf, dass des unsauber ist die Attributnamen und Maßeinheiten aus der Datenbank in die Anwendung quasi "hardcoded" zu packen.


----------



## nillehammer (27. Jul 2011)

> Hm, nicht ganz. Es gibt viele Maschinen, welche aber alle diesselben Attribute besitzen (nur mit verschiedenen Werten natürlich). Aber jede Maschine hat ein Drehmoment, eine max. Drehzahl, etc. Das Problem dabei ist jetzt, dass zB das Attribut "Schwenkwinkel B" Werte wie max. und min. Winkel beschreiben, während ein anderes Attribut wieder durch einen String oder eine Folge von Ganzzahlen beschrieben wird. Daher dachte ich daran, dass jedes Attribut eigentlich eine eigene Klasse sein müsste. Außerdem sind die Attribute auch noch in Gruppen unterteilt.


Ok, dann hab ich's falsch verstanden und es ist kein Fall von Vererbung. Zu dem Design schlage ich folgendes vor (wieder objektorientier, aber wenn wir das fertig haben, leitet sich das DB-Design autmatisch ab). Pack so viel wie möglich als prmitive Attribute in die Klasse Maschine. Dort, wo es fachlich Sinn macht, definiere eine separate Klasse, die Teilmengen der Attribute aufnimmt (die dann natürlich nicht mehr bei Maschine sind). "Schwenkwinkel" wäre z.B. ein Kandidat für eine separate Klasse. Es stellt fachlich etwas eigenes dar und braucht auch eigene Zusicherungen (z.B. minWinkel < maxWinkel). Die Gruppierung sieht für mich erstmal nach einem rein visuellen Aspekt aus, den ich nicht im Datenmodell abbilden würde. Wenn Du das Klassenmodell einigermaßen weit hast, dan poste mal einen Entwurf und wir machen ein DB-Design draus.
Gruß nillehammer

P.S.


> Jedenfalls wäre eine Tabelle mit ca 60 Spalten auch nicht ungewöhnlich.
> Es ginge durchaus alle Attribute in einer Tabelle abzuspeichern.
> Du verschwendest etwas Plattenplatz, wenn von den 60 Attributen im Schnitt kleiner 10 belegt sind. Aber, ist das wichtig?


Das ist ein ganz schlechtes Vorgehen! Auf keinen Fall machen! Ich will hier nicht auf die Einzelheiten eingehen, aber das Stichwort ist hier "Normalform".


----------



## heart_disease (27. Jul 2011)

So, erstmal vielen Dank für deinen Input. Ich hab mal notdürftig mit PowerPoint ein Klassendiagramm mit Relationen entworfen (siehe JPG im Anhang). Ich hoffe ich hab die Beziehungen richtig angeschrieben ^^'.

PS: Kleiner Fehler in der Tabelle "machines": das Feld manufacturer_id ist natürlich ein FK (foreign key)!


----------



## nillehammer (27. Jul 2011)

Danke für das Diagramm, damit kann man ja schonmal arbeiten. Du hast übrigens ein ER-Diagramm geliefert. Erkennbar ist das an den Kardinalitäten und an den Pfeilen, die hier die REFERENCES darstellen. In einem Klassendiagramm wären die Kardinalitäten genau anders herum. Und Pfeile würde man für Navigationsrichtungen benutzen.

Aber genug der Klugs*****errei und wieder zurück zum Fachlichen. Ich bin mir noch nicht sicher, ob ich verstanden habe, was Du machen willst. Ich sehe in Machine nur ein Feld für generic_attribute. Du hattest aber von vielen gesprochen. Sollen die "..." direkt darunter das zum Ausdruck bringen?


----------



## heart_disease (27. Jul 2011)

Ja genau. Das "generic" steht hier nur für "beliebig". Es gibt also schlussendlich so um die 60 Attribute. Das was aber alle Attribute gemeinsam haben, wird wieder in "attribute_metadata" zusammengefasst. Die "attribute_id" von einer beliebigen Attributklasse (das wäre dann so ein "generic_attribute", wie zB "Schwenkwinkel B") ist dann übrigens dieselbe, wie die "attribute_id" von dem dazugehörigen Datensatz in "attribute_metadata". Ein "shared primary key", wenn man das so sagen kann. Sonst müsste ich ja eigentlich sinnlos noch ein zusätzliches Schlüssel-Feld einführen.

Das mit dem "generic" hätte ich vlt. noch dazu erklären sollen, entschuldige die Verwirrung.


----------



## nillehammer (27. Jul 2011)

Ok, jetzt hab ich's glaub ich verstanden. Deine Maschine hat halt sehr viele Attribute, die willst Du nicht alle einzeln als Spalten haben. Deswegen hast Du Dir das Konzept mit den Attributen überlegt. Darüber hinaus willst Du eine gewisse Flexibiliät beim Typ der Attribute. Deswegen dieses "generic". Damit die Attribute nicht nur so "lose" an den Maschinen dran hängen und weil gewisse Attribute eben fachlich zusammen gehören (z.B. minWinkel, maxWinkel bei Drehwinkel), willst Du um einige eine "Klammer" drum haben. Deswegen die AttributGruppe. Das sind alles verständliche Anforderungen und es ist auch umsetzbar. Ich habe leider nur LibreOffice und kotze jedes Mal, wenn ich da eine Präsi mit machen muss. Deswegen versuche ich die Strukur mal textuell zu beschreiben.

```
Manufacturer {
  id:bigint, pk
  name: varchar, not null (evtl. unique?)
}

Machine {
  id: bigint, pk
  manufactuer_id: bigint, fk(Manufacturer.id), not null
  name: varchar, not null (evtl. unique?)
}

AttributeGroup {
  id: bigint, pk
  name: varchar, not null, (evtl. unique?)
}

AttributeMetaData {
  id: biging, pk
  attributeGroup_id: bigint, fk(AttributeGroup.id), not null (oder null zulassen, wenn es auch AttributMetadata ohne Gruppenzuordnung geben soll)
  identifier_de: varchar, not null (evtl. unique?)
  unit: varchar, not null
}
```

Ein komplett generischer Ansatz geht in der Datenbank nicht, irgendeinen Typ müssen die Spalten ja haben. Außer, du machst alles mit varchar und versuchst dann in der Anwendung Typen wie Integer, Boolean, String draus zu machen. Ist aber bestimmt umständlich. Deswegen weiche ich hier Dein generisches Konzept etwas auf und führe "getypte" Attributtabellen ein.

```
LongAttribut {
  machine_id: bigint, fk(Machine.id), not null
  attributMetadata_id: bigint, fk(AttributMetaData.id), not null
  value: bigint, not null
  unique(machine_id,attributMetaData_id)
}

StringAttribut {
  machine_id: bigint, fk(Machine.id), not null
  attributMetadata_id: bigint, fk(AttributMetaData.id), not null
  value: varchar, not null
  unique(machine_id,attributMetaData_id)
}
... ggf. weitere Tabellen für Attributtypen, z.B. Boolean...
```
Du siehst, dass die Beziehung von Machine zu AttributeMetadata weggefallen ist und das die Foreign Keys zu Machine und AttributeMetadata jetzt in den xxxAttribut-Tabellen stecken. Auf diese Weise kannst Du jeder Maschine beliebig viele Attribute beliebigen Typs zuweisen. Zwei Dinge sind aber so (noch) nicht realisiert:

Es ist mit dem Datenmodell mögich, dass eine Maschine z.B. nur zwei Attribute hat, eine andere aber 50. Es ist also nicht sicher gestellt, dass alle Maschinen die gleiche Anzahl Attribute haben und die Typen auch alle gleich sind.
Es wäre möglich, dass es einmal ein Attribut gibt, dass auf AttributMetadata "Drehmoment" zeigt, was vom Typ Long ist und ein anderes Attribut, dass auf denselben AttributMetadata zeigt, welches selbst aber vom Typ String ist.
Wenn Dich die beiden Sachen nicht stören, wären wir fertig.


----------



## schalentier (28. Jul 2011)

@heart_disease: Beschreib mal noch ein bisschen genauer, was du eigentlich machen willst. 

Das was jetzt hier von nillehammer beschrieben wurde, scheint mir irgendwie mit Kanonen auf Spatzen geschossen. Mit diesem Modell kannst du dann zur Laufzeit neue Attribute an Maschinen haengen. Ist das _wirklich_ so gewuenscht? Ueberleg einfach mal, wie ein paar DB Queries aussehen wuerden, z.B. "Gibt mir alle Maschinen mit einem Drehwinkel groesser 23". Dafuer brauchst du mindestens zwei JOINS. Willst du alle Attribute einer Maschine (z.B. fuer den Edit-Dialog), haste wahlweise 60 JOINS (_NICHT MACHEN!!_) oder viele Selects (auch schlecht!). 

Das Gruppieren der Attribute ist wofuer genau? Wenn das nur eine visuelle Sache ist, gehoert das definitiv _nicht_ in die Datenbank...

Beantworte auch mal die Frage vom homer65. Um wieviele Maschinen/Maschinentypen geht es? Ist es nicht sinnvoller, jeden Maschinentyp als eigne Klasse mit festen Attributen zu modelieren? Da kannst du auch Vererbung eventuell sinnvoll benutzen und dich beim DB Mapping wahlweise fuer Single-Table- oder Multi-Table-Inheritance entscheiden.

Tabellen mit 60 oder mehr Spalten, von denen viele oftmals null sind, ist im uebrigen tatsaechlich nichts ungewoehnliches. Wichtig ist dann nur, alle notwendigen Spalten im Select anzugeben und nicht immer mit "SELECT * FROM ..." zu selektieren.


----------



## heart_disease (28. Jul 2011)

schalentier hat gesagt.:
			
		

> Mit diesem Modell kannst du dann zur Laufzeit neue Attribute an Maschinen haengen. Ist das wirklich so gewuenscht?


Wäre benutzertechnisch kein Nachteil, ist aber nicht gefordert.



			
				schalentier hat gesagt.:
			
		

> Beantworte auch mal die Frage vom homer65. Um wieviele Maschinen/Maschinentypen geht es? Ist es nicht sinnvoller, jeden Maschinentyp als eigne Klasse mit festen Attributen zu modelieren?


Es handelt sich im Moment um 22 Maschinen, es ist allerdings auf jeden Fall gefordert dass bequem neue Maschinen angelegt werden können. Weiters gibt es keine speziellen Maschinentypen (zumindest in der DB-Logik nicht), da alle Maschinen exakt diesselben Attribute aufweisen. Es geht im Prinzip darum, eine primitive Excel-Tabelle mit Maschinendaten in eine Datenbankstruktur zu transformieren.



			
				nillehammer hat gesagt.:
			
		

> Es ist mit dem Datenmodell mögich, dass eine Maschine z.B. nur zwei Attribute hat, eine andere aber 50. Es ist also nicht sicher gestellt, dass alle Maschinen die gleiche Anzahl Attribute haben und die Typen auch alle gleich sind.


Das ist kein Problem, es ist ohnehin so, dass besonders bei Konkurrenzmaschinen nicht alle Daten bekannt sind. Ein bestimmtes Attribut muss allerdings auch immer genau denselben Typ haben!



			
				nillehammer hat gesagt.:
			
		

> Es wäre möglich, dass es einmal ein Attribut gibt, dass auf AttributMetadata "Drehmoment" zeigt, was vom Typ Long ist und ein anderes Attribut, dass auf denselben AttributMetadata zeigt, welches selbst aber vom Typ String ist.


Hm, das wäre dann ein Fall für die Integritätssicherung. Die werde ich wohl oder übel in die Business Logic auslagern müssen - sprich in den Java-Code. Ich arbeite nämlich mit SQLite, das hat soetwas meines Wissens nicht.


Ich hab mein ER-Modell von gestern jetzt noch einmal abgeändert und eine überflüssige Beziehung entfernt. Hoffe es ist diesmal aussagekräftiger. Der "GenericDataType" ist kein wirklicher Datentyp, sondern ist nur ein Platzhalter weil ja jedes Attribut seine Werte anders abspeichert.


*EDIT:* Mir ist gerade noch etwas eingefallen. Um beliebige Zahlenketten zu speichern könnte ich doch eine zusätzliche Tabelle [integer_values] einführen, welche eine Referenz auf [attribute_metadata] enthält. Wie von nillehammer vorgeschlagen, müsste ich dazu dann bei [attribute_metadata] ein eigenes Feld für den Datentyp einführen (1 = einfache Zahl, 2 = Zahlenfeld, 3 = String, etc.). Dafür würden dann natürlich die vielen Attribut-Tabellen wegfallen.


----------



## schalentier (28. Jul 2011)

heart_disease hat gesagt.:


> Weiters gibt es keine speziellen Maschinentypen (zumindest in der DB-Logik nicht), da alle Maschinen exakt diesselben Attribute aufweisen. Es geht im Prinzip darum, eine primitive Excel-Tabelle mit Maschinendaten in eine Datenbankstruktur zu transformieren.



Warum machst du dann nicht einfach eine Tabelle mit den gleichen Spalten wie in der Exceltabelle? Warum willst du eine 1:n Beziehung zwischen Maschine <-> Attribut? Das halte ich fuer ueberfluessig, vor allem wenn alle Maschinen die gleichen Attribute haben...


----------



## heart_disease (28. Jul 2011)

Ich hab mein altes Konzept jetzt nochmal über den Haufen geschmissen und den Ansatz von nillehammer verfolgt. Bei den Relationen bin ich mir allerdings noch nicht ganz sicher, ob alle richtig gesetzt sind.


----------

