Sinnvolles Design einer Datenbank

Hallo Zusammen!

Ich habe mal eine Frage die das Design einer Datenbank betrifft. Ich kenne mich mit dieser Thematik leider nicht aus und hoffe daher, dass Ihr mir meine evtl. etwas dümmliche Frage nachseht.

Es geht grob gesagt um redundante Daten. Nun bin ich der Meinung, dass redundante Daten vermieden werden sollten aber je mehr ich darüber nachdenke desto mehr bin ich der Ansicht, dass in manchen Fällen Redundanzen einfach in Kauf zu nehmen sind.

Ich möchte mein Problem anhand von drei Beispielen verdeutlichen. Es geht jeweils um eine Tabelle mit offenen Posten (OP) und um die dazugehörenden Zahlungsbedingungen.

Was meint Ihr welches der folgenden drei Beispiele die beste Vorgehensweise darstellt?

Im ersten Beispiel werden in dem OP Datensatz alle relevanten Informationen der Zahlungsbedingung abgespeichert - eigentlich nicht notwendig, da man sich diese Informationen jederzeit berechnen kann wie man nachher sehen wird. Der Vorteil wäre, dass immer wenn Daten der Zahlungsbedingung benötigt werden direkt auf die in dem OP Datensatz abgespeicherten Daten zugegriffen werden können und keine weiteren Selektionen anderer Tabellen notwendig wären.
Das ganze würde dann wie folgt aussehen.

OP:
Konto, Belegnummer, Betrag, Buchungsdatum, Datum_Skontofrist1, Skontosatz1, Datum_Skontofrist2, Skontosatz2, Endfälligkeitsdatum
99999, 87654, 100,00, 01.01.11, 10.01.11, 4%, 31.01.11, 2%, 28.02.11

Wenn ich nun wissen möchte wie viel Skonto sich der Kunde ziehen kann kann ich das aktuelle Datum der Reihe nach mit Datum_Skontofrist1 bis Endfälligkeitsdatum vergleichen und hätte so relativ einfach den Skontosatz. Möchte ich den Kunden mahnen müsste zB nur das Endfälligkeitsdatum mit dem aktuellen Datum verglichen werden. Die Last für den Datenbankserver wäre so gesehen eher gering, da keine weiteren Abfragen an den Server geschickt werden müssten.

Ich denke außerdem, dass es bei den heutigen Massenspeichern nicht auf den Verbrauch von Speicherplatz ankommt. So gesehen würden in dieser Version bei 1 Mio Datensätzen pro Jahr etwa [34 Byte (Datum) + 21 Byte (Skonto) = 14 Byte - Zuordnung 3 Byte = 11 Byte] 11 MB Speicher verschwendet werden.

Im nächsten Beispiel gibt es zwei Tabellen. Eine mit dem OP, eine mit der Zahlungsbedingung. Das ganze würde wie folgt aussehen.

Zahlungsbedingung:
ID, Bezeichnung, Tage1, Skontosatz1, Tage2, Skonto2, Endfällig
100, ‘10 Tage 4%, 30 Tage 2%, 60 Tage netto’ 10, 4%, 30, 2%, 60

OP:
Konto, Belegnummer, Betrag, Buchungsdatum, ZahlungsbedingungID
9999, 87654 100,00, 01.01.11, 100

Wenn ich nun wissen möchte ob die Endfälligkeit überschritten wurde müsste ich erst einmal über die Zahlungsbedingung ermitteln in wie viel Tagen die Forderung endfällig ist, dann das Endfälligkeitsdatum ausrechnen und dann mit dem aktuellen Datum vergleichen. Um das nicht mit jedem offenen Posten einzeln machen zu müssen denke ich, dass es wohl sinnvoll wäre ein Sicht zu erzeugen.

Ich denke, das dies bereits ein guter Ansatz ist, wenngleich dieser Ansatz in Bezug auf die Anzahl der möglichen Zeitbänder innerhalb der Zahlungsbedingung sehr unflexibel ist da nur drei Zeiträume angegeben werden können.

Um das ganze noch etwas zu übertreiben nun noch eine weitere Version. Hier können einer Zahlungsbedingung nun beinahe unbegrenzt viele Zeitbänder zugeordnet werden. Es gibt nun eine Tabelle in der die Zeitbänder für die einzelnen Fristen gespeichert sind. Eine weitere Tabelle um die Zeitbänder einer Zahlungsbedingung zuzuordnen. In dieser Tabelle können einer Zahlungsbedingung beliebig viele Zeitbänder zugeordnet werden. Es gibt die Tabelle mit der Zahlungsbedingung und die Tabelle mit dem OP. Das ganz sieht wie folgt aus.

Zeitbänder:
ID, Tage, Skontosatz
10, 5, 5%
20, 10, 4%
30, 20, 3%
40, 30, 2%
50, 60, 0%

Zuordnung:
ID, Reihenfolge, ZeitbänderID
AA, 1, 10
AA, 2, 20
AA, 3, 30
AA, 4, 40
AA, 5, 50
BB, 1, 20
BB, 2, 40
BB, 3, 50

Zahlungsbedingung
ID, Bezeichnung, Zuordnung
100, ‘10 Tage 4%, 30 Tage 2%, 60 Tage netto’, BB

OP:
Konto, Belegnummer, Betrag, Buchungsdatum, Zahlungsbedingung
9999, 87654 100,00, 01.01.11, 100

Wenn ich nun etwas über die Zahlungsbedingung herausfinden möchte wird es (für meine Begriffe) reichlich kompliziert. Um einen Skontosatz zu erfahren müssten alleine drei Tabellen abgefragt werden und das mit unterschiedlich komplizierten Selektionen. Sicherlich könnte man sich aus den Tabellen auch eine Sicht bauen aber im Vergleich zu Beispiel Zwei würde das wahrscheinlich eine wesentlich höhere Last für den Server bedeuten.

Wenn du selbst zugibst, das du dich mit der Thematik nicht auskennst, dann möchte ich dir die Thematik “Normalform” anvertrauen.
Bitte lies dir etwas Literatur zu diesem Thema durch, der Wikipedia Artikel ist ein guter Start.

Ohne diese Grundlagen wirst du arge Probleme haben, ein vernünftiges Datenbankdesign in einer relationalen Datenbank zu erstellen.

Manchmal kann man Redundanzen wegen einer besseren Performance tolerieren, ansonsten machen sie einem das Leben unnötig schwer, schliesslich muß ich unter Umständen Änderungen und Kontrollen an mehreren Stellen durchführen. Sinn macht das IMHO nur bei richtig großen und komplexen Datenbeständen ala Datawarehouse oder teilweise auch Geometriedaten, bei allem was darunter liegt dürften die Vorteile eines sauberen Designs überwiegen.

Gruß Uwe

Hi,

IMHO gibt es darauf keine allgemeingültige Antwort. Prinzipiell sollte man Redundanzen natürlich vermeiden. Aber ich sehe das nicht als Dogma. Es ist zwar nicht ganz korrekt, aber ich mache mir beim DB-Design auch schon ein wenig Gedanken, was ich mal auswerten könnte und welcher Aufwand dann für eine Abfrage entstehen würde. So kumuliere ich z.B. die Warenumsätze unserer Kunden in ein paar Feldern der Kundendatei. Theoretisch könnte ich sie ja immer aus den Rechnungsdaten generieren, was redundanzfrei wäre. Aber im Interesse eines schnelleren Überblicks nehme ich das einfach in Kauf, weil der sehr oft gebraucht wird.

In Deinem konkreten Beispiel ist es bei mir so: Ich habe eine Tabelle mit Zahlungsbedingungen (deine Variante 2), ich habe noch niemanden gefunden, der mit 2 Skontosätzen/Zeiträumen und der Endfälligkeit nicht ausgekommen wäre. In meiner Kundendatei steht die ZahlungsbedingungsID. Bei Rechnungslegung wird die vorgeschlagen, kann aber durch eine andere gültige ID ersetzt werden. Diese ID wird mit dem OP dann gespeichert. Außerdem aber das Datum der Endfälligkeit. Denn es macht schon einen Unterschied, ob ich das beim Erstellen einer Mahnliste erst errechnen lassen muss oder ob es sofort zu sehen ist, das ein OP überfällig ist. Natürlich ist es aber letztlich redundant…
Die Skonti brauche ich ja eher selten. Wenn ein Kunde zahlt, habe ich es mit einem einzigen OP zu tun, da macht das bißchen Abfrage nicht viel aus und Analysen zum Thema Skonti sind doch eher selten.

just my 2 ct

cu jth

Man könnte hier als Brückenschlag zwischen sauberem Design und Performanceund der Vollständigkeit wegennoch Materialized Views erwähnen, die die auszuwertenden Daten aufbereitet bereitstellen können.
Man erkennt, der Möglichkeiten sind Legion… :wink:

Gruß Uwe

Hallo Zusammen!

Vielen Dank für Eure Antworten.
@jth vielen Dank für Dein Beispiel!

ich denke, dass das Hauptaugenmerk darauf liegen sollte Redundanzen zu vermeiden und gleichzeitig dafür Sorge zu tragen, dass regelmäßig vorkommende Abfragen die Kapazität eines System nicht zu stark belasten.

Ein Problem, viele Lösungen. Man muss sich “nur” für die beste Lösung entscheiden :slight_smile: