Normalisierung: Wird es als konform angesehen, statische numerische Werte wie ein Jahr in eine eigene Tabelle aufzuteilen?


16

Ich habe eine interessante Diskussion mit einem anderen Datenbankdesigner über Normalisierung. In diesem Beispiel haben wir eine GameTitles-Tabelle und jeder Datensatz muss das Jahr enthalten, in dem das Spiel veröffentlicht wurde. Er sagt, dass 2NF vorschreibt, dass alles normalisiert werden muss. Um konform zu sein, sollte das Jahresfeld in eine ReleaseYears-Tabelle mit einem eigenen Primärschlüssel aufgeteilt werden, auf den die GameTitles-Tabelle verweist. Ich sage, es sollte als Feld auf dem GameTitles-Tisch selbst bleiben.

Mein Argument dafür ist, dass ein Jahr nur ein nicht-primitiver numerischer Wert ist, der von Natur aus statisch ist (dh 2011 wird immer 2011 sein). Aus diesem Grund dient es als eigene Kennung und muss nicht referenziert werden, da es das ist, was es ist. Dies führt auch zu einer zusätzlichen Wartung, da Sie der Tabelle jetzt ein neues Jahr hinzufügen müssen, um darauf zu verweisen. Wenn Sie die Tabelle mit einem großen Bereich von Jahren vorab ausfüllen, verfügen Sie über zusätzliche Datensätze, auf die möglicherweise überhaupt keine Verweise vorhanden sind. Dies erhöht auch die Datenbankgröße, da Sie jetzt über eine zusätzliche Tabelle, einen zusätzlichen Datensatzaufwand und den zusätzlichen Primärschlüssel für das Jahr selbst verfügen. Wenn Sie das Jahr als Feld in der GameTitles-Tabelle behalten, entfallen all diese zusätzlichen Wartungs- und Verwaltungskosten.

Gedanken dazu?

edit: Soll dies auf StackOverflow posten. Kann jemand abstimmen, um dies zu löschen oder um es zur Aufmerksamkeit zu melden?


6
Warum so? es scheint hier gut zu passen.
Leigh Riffel

Die Frage, die ich stellen möchte, ist, ob Sie diese Frage zur Normalisierung oder zum tatsächlichen Produktionsbedarf stellen. Für die Produktion würde ich fragen, ob das eine berechtigte Sache ist?
Jcolebrand

Antworten:


14

Der andere Datenbankdesigner ist einfach falsch, aber auch Ihre Argumentation ist falsch. Angenommen, Sie beginnen mit dieser Tabelle, die einen einzelnen Kandidatenschlüssel "game_title" enthält.

Table: game_titles

game_title                      year_first_released
--
The first game                  1998
The second game                 1999
Best game: the third one        2001
The fourth game                 2003
Forty-two, the end of games     2011

Sie bewerten, ob es in 2NF ist, indem Sie sich diese Fragen stellen.

F: Zuallererst ist es in 1NF?

A: Ja, das ist es.

F: Was sind die Hauptattribute (Attribute, die Teil eines Kandidatenschlüssels sind)?

A: "game_title" ist das einzige Hauptattribut.

F: Was sind die Nicht-Prim-Attribute?

A: "year_first_released" ist der einzige.

F: Ist "year_first_released" funktional abhängig von "game_title" oder nur von einem Teil davon?

A: Der einzige Kandidatenschlüssel "game_title" ist eine einzelne Spalte. es hat nicht einmal Teile. "Year_first_released" ist also funktional abhängig von "game_title".

Voilà. Sie haben 2NF gefunden.

Sie können einige der formalen Begriffe durchgehen, indem Sie zuerst fragen, ob es sich um 1NF handelt, und dann diese Frage beantworten.

F: Gibt es zusammengesetzte Kandidatenschlüssel?

A: Nein.

Voilà. Sie haben wieder 2NF gefunden.

Per Definition muss eine Tabelle mindestens einen Kandidatenschlüssel mit mehr als einer Spalte haben, damit sie gegen 2NF verstößt.

Hier sind Ihre Gründe, die Meinung Ihres Freundes abzulehnen.

  • Ein Jahr ist nur ein nicht-primitiver numerischer Wert.
  • Ein Jahr ist von Natur aus statisch.
  • Ein Jahr dient als eigene Kennung.
  • Eine Tabelle von Jahren führt zusätzliche Wartung ein.
  • Eine Jahrestabelle enthält möglicherweise zusätzliche Zeilen, auf die nicht verwiesen wird.
  • Eine Tabelle von Jahren erhöht die Datenbankgröße.

Keiner dieser Gründe hat etwas damit zu tun, ob sich eine Tabelle in 2NF befindet.

Beim Entwerfen einer Datenbank ist es nicht falsch, Wartungsprobleme, Datenbankgröße, nicht referenzierte Zeilen, Bereichsbeschränkungen usw. zu berücksichtigen. Es ist einfach falsch, diese Dinge als Normalisierung zu bezeichnen.

Oh, und diese zweispaltige Tabelle, die ich oben bereitgestellt habe - es ist in 5NF.


2
Schön gemacht. Ich war versucht, eine Antwort zu veröffentlichen, die nichts anderes aussagte als Ihren ersten Satz ... "Der andere Datenbankdesigner ist einfach falsch", Sie haben das Warum sehr gut behandelt.
Mark Storey-Smith

5

Das Erstellen einer separaten Tabelle für ein Attribut hat nichts mit Normalisierung zu tun. 2NF, 3NF, BCNF, 4NF, 5NF befassen sich alle mit der Beseitigung von Nicht-Schlüssel-Abhängigkeiten. Wenn Sie ein einzelnes Attribut in einer neuen Tabelle entfernen und durch ein Fremdschlüsselattribut ersetzen, werden die Abhängigkeiten in der Tabelle logischerweise genauso sein wie zuvor. Die überarbeitete Version der Tabelle wird also nicht mehr oder weniger normalisiert war vorher.


Ich möchte noch etwas hinzufügen , bin mir aber nicht sicher, was. Sie sagen, dass das Verschieben von Elementen in eine Tabelle mit einer 1: 1-Korrelation (entweder 1 Schlüssel für genau 1 Wert wie in diesem Fall oder eine Zeile für eine Zeile) keinen Vorteil bringt, wenn die Suche nicht benötigt wird, oder? Aber es gibt einen potenziellen Nachschlagevorteil, wenn Sie das Jahr selten benötigen und nur einen Bereich von 255 Jahren oder weniger betrachten. Es ist denkbar, dass Sie hier mit ein paar gesparten Bytes davonkommen, aber da diese normalerweise sowieso mit 4 Byte belegt sind, ist dies keine vernünftige Annahme.
jcolebrand

1
@jcolebrand: Stimmen Sie dem zu, was Sie sagen. Die Antwort auf die Frage ist immer noch die gleiche: Ob Sie es tun oder nicht, hat nichts mit Normalisierung per se zu tun.
nvogel

Ich stimme zu. Wie ich schon sagte, war meine halbherzig "Ich habe das Gefühl, dass dem OP hier etwas fehlt" ... weil ich nicht sicher bin, wohin ich mit diesem Konzept gehen soll.
Jcolebrand

5

Aus meiner Sicht ist eine separate Jahrestabelle nur dann sinnvoll, wenn das "Erscheinungsjahr" kein Kalenderjahr ist, sondern zB ein Geschäftsjahr, das mehrere Kalenderjahre umfassen kann (zB von Oktober bis Oktober).

Diese Tabelle würde dann die Definition (reales Start- und Enddatum) des Geschäftsjahres enthalten


1
+1 Sie brauchen nur eine Tabelle, wenn es Attribute haben wird :)
Jack Douglas

2

Aus http://en.wikipedia.org/wiki/Second_normal_form :

Eine 1NF-Tabelle ist nur dann in 2NF, wenn angesichts eines Kandidatenschlüssels K und eines Attributs A, das kein Bestandteil eines Kandidatenschlüssels ist, A von der Gesamtheit von K abhängt und nicht nur von einem Teil davon.

Sie haben nicht angegeben, ob das Jahr Teil des Kandidatenschlüssels ist oder nicht, aber ich bin nicht sicher, ob es von Bedeutung ist, da 2NF in beiden Fällen in Bezug auf das Jahr zufrieden wäre.

Aus praktischen Gründen ist es eine schlechte Idee, das Jahr aus all Ihren Gründen zu trennen.


2

Ich mag das Argument gegen die separate Tabelle nicht, weil sie so groß ist oder nicht verwendete Zeilen enthält. Selbst wenn Sie 1000 Jahre in diese Tabelle eingeben, ist die Größe vernachlässigbar.

Trotzdem glaube ich nicht, dass der Tisch überhaupt gebraucht wird. Was nützt es, eine separate Tabelle für das Jahr zu haben? Diese Daten befinden sich bereits in der Haupttabelle und Sie sparen absolut nichts, indem Sie eine zweite Tabelle erstellen.

Das Argument kann für eine Kalendertabelle unterschiedlich sein, wobei jede Zeile einen Tag darstellt und andere Attribute haben kann (Wochentag, UTC-Offset, ob es sich um einen Feiertag handelt usw.).

Aber das ganze Jahr allein? Nein, ich sehe überhaupt keinen Nutzen ... Und wie andere darauf hingewiesen haben, fragen Sie sie, warum sie denken, dass dies normaler ist? Oder was gewinnen sie? Wenn Sie versuchen, Fragen wie zu schreiben

WHERE othertable.year = 2011

Anstatt von

WHERE dt >= 20110101 AND dt < 20120101

Dann würde ich versuchen, Sie davon zu überzeugen, dass Letzteres für die Leistung (unter der Annahme, dass dt indiziert ist) und die Speicherung viel besser ist. Wenn die Einfachheit der Codierung von größter Bedeutung ist, würde ich sagen, dass eine dauerhaft berechnete Spalte besser ist als eine andere Tabelle.


1

Ich stimme der Antwort von Catcall vollkommen zu, außer in einem Punkt: "Jahr" ist vielleicht nicht immer ein primitiver Wert, aber ich denke, das ist eher ein Geschäftslogik-Konzept als ein Datenbank-Design-Konzept.

Nehmen wir an, dass die Jahre bei gleichem Design nur die Jahre sein sollten, für die die Freigabe zulässig ist. Auf diese Weise haben Sie es nicht mit primitiven numerischen Werten zu tun, sondern mit einer Teilmenge davon, und da eine solche Teilmenge keine primitive Implementierung hat, müssen Sie Ihre eigene (eine separate Tabelle?) Erstellen und darauf verweisen (mit einem FK). Auf diese Weise sprechen wir immer noch von Jahren, aber wir müssen sie auf eine andere Weise verwalten, weil sie konzeptionell ihre Bedeutung geändert haben. Sie sind zwar immer noch "Erscheinungsjahr", aber konzeptionell anders, was sie für jemanden mit Domänenkenntnissen bedeuten.

Für diesen speziellen Fall sage ich noch einmal, dass Catcalls Antwort richtig ist, wollte aber nur darauf hinweisen. (Entschuldigung, ich habe noch nicht genug Repräsentanten, um einen Kommentar abzugeben.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.