Normalisation: Est-il considéré comme conforme de diviser des valeurs numériques statiques comme une année dans leur propre tableau?

16

J'ai une discussion intéressante avec un autre concepteur de base de données sur la normalisation. Dans cet exemple, nous avons une table GameTitles et chaque enregistrement doit contenir l'année de sortie du jeu. Il dit que 2NF exige que tout soit normalisé, donc, pour être conforme, le champ année doit être divisé en une table ReleaseYears avec sa propre clé primaire référencée par la table GameTitles. Je dis que cela devrait rester comme un champ sur la table GameTitles elle-même.

Mon argument pour cela est qu'une année n'est qu'une valeur numérique non primitive qui est statique par sa nature même (c'est-à-dire que 2011 sera toujours 2011). De ce fait, il sert de son propre identifiant et n'a besoin de rien pour le référencer puisqu'il est ce qu'il est. Cela introduit également une maintenance supplémentaire puisque vous devez maintenant ajouter une nouvelle année au tableau juste pour la référencer. Si vous préremplissez le tableau avec un large éventail d'années, vous disposez alors d'enregistrements supplémentaires qui n'auront potentiellement aucune référence à eux. Cela augmente également la taille de la base de données, car vous disposez désormais d'une table supplémentaire, d'un surcoût d'enregistrement et de la clé primaire supplémentaire pour l'année elle-même. Si vous conservez l'année comme champ sur la table GameTitles, vous éliminez tous ces frais de maintenance et frais généraux supplémentaires.

Réflexions là-dessus?

edit: destiné à publier ceci sur StackOverflow. Quelqu'un peut-il voter pour le supprimer ou le signaler à l'attention?

stoogemuffin
la source
6
Pourquoi donc? cela semble être un bon choix ici.
Leigh Riffel
La question que je veux poser est la suivante: posez-vous cette question sur la normalisation ou les besoins réels de production? Pour la production, je demanderais si c'est une chose valable à faire?
jcolebrand

Réponses:

14

L'autre concepteur de base de données a tout simplement tort, mais votre raisonnement est également faux. Supposons que vous commenciez par cette table, qui a une seule clé candidate, "game_title".

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

Vous évaluez si c'est dans 2NF en vous posant ces questions.

Q: Tout d'abord, est-ce en 1NF?

R: Oui, ça l'est.

Q: Quels sont les principaux attributs (attributs qui font partie d'une clé candidate)?

R: "game_title" est le seul attribut principal.

Q: Quels sont les attributs non premiers?

R: "year_first_released" est le seul.

Q: "year_first_released" est-il fonctionnellement dépendant de l'ensemble de "game_title", ou d'une partie seulement de celui-ci?

R: La seule clé candidate, "game_title", est une seule colonne; il n'a même pas de pièces. Donc "year_first_released" est fonctionnellement dépendant de l'ensemble de "game_title".

Voilà. Vous avez trouvé 2NF.

Vous pouvez couper certains des termes formels en demandant d'abord si c'est en 1NF, puis en répondant à cette question.

Q: Existe-t-il des clés candidates composites?

R: Non.

Voilà. Vous avez retrouvé 2NF.

Par définition, pour qu'une table viole 2NF, elle doit avoir au moins une clé candidate qui a plus d'une colonne.

Voici vos raisons de rejeter l'opinion de votre ami.

  • Une année n'est qu'une valeur numérique non primitive.
  • Une année est statique de par sa nature même.
  • Une année sert de son propre identifiant.
  • Un tableau des années introduit une maintenance supplémentaire.
  • Un tableau d'années peut contenir des lignes supplémentaires qui ne sont pas référencées.
  • Un tableau des années augmente la taille de la base de données.

Aucune de ces raisons n'a quoi que ce soit à voir avec le fait qu'une table soit en 2NF.

Lors de la conception d'une base de données, il n'est pas faux de prendre en compte les problèmes de maintenance, la taille de la base de données, les lignes non référencées, les contraintes de plage, etc. C'est juste faux d'appeler ces choses normalisation.

Oh, et ce tableau à deux colonnes que j'ai fourni ci-dessus - il est en 5NF.

Mike Sherrill 'Cat Recall'
la source
2
Bien fait. J'ai été tenté de poster une réponse qui ne disait rien d'autre que votre première phrase ... "L'autre concepteur de base de données a tout simplement tort", vous avez très bien couvert le pourquoi.
Mark Storey-Smith
5

La création d'une table distincte pour n'importe quel attribut n'a rien à voir avec la normalisation. 2NF, 3NF, BCNF, 4NF, 5NF sont tous concernés par l'élimination des dépendances non clés. Si vous supprimez un attribut unique dans une nouvelle table et le remplacez par un attribut de clé étrangère, les dépendances dans la table seront logiquement les mêmes qu'avant - de sorte que la version révisée de la table n'est ni plus ni moins normalisée qu'elle était avant.

nvogel
la source
Je veux ajouter quelque chose à cela, mais je ne sais pas quoi. Vous dites que déplacer quelque chose dans une table qui a une corrélation de 1: 1 (soit 1 clé pour exactement 1 valeur comme dans ce cas, soit une ligne sur une ligne) ne donne aucun avantage si la recherche n'est pas nécessaire, non? Mais il existe un avantage de recherche potentiel si vous avez rarement besoin de l'année et que vous ne regardez que 255 ans ou moins. On pourrait imaginer s'en tirer avec quelques octets enregistrés ici, mais puisque normalement ils sont alloués à 4 octets de toute façon, ce n'est pas une hypothèse raisonnable.
jcolebrand
1
@jcolebrand: d'accord avec ce que vous dites. La réponse à la question est toujours la même: que vous le fassiez ou non n'a rien à voir avec la normalisation en soi.
nvogel
Je suis d'accord. Comme je l'ai dit, le mien était un peu timide "J'ai l'impression que l'OP manque quelque chose ici" ... parce que je ne sais pas où aller avec ce concept.
jcolebrand
5

De mon point de vue, une table des années distincte n'aurait de sens que si "l'année de sortie" n'est pas une année civile, mais par exemple un exercice financier qui peut s'étendre sur plusieurs années civiles (par exemple allant d'octobre à octobre).

Ce tableau contiendrait alors la définition (date réelle de début et de fin) de l'exercice

un cheval sans nom
la source
1
+1 vous n'avez besoin d'une table que si elle va avoir des attributs :)
Jack Douglas
2

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

une table 1NF est dans 2NF si et seulement si, étant donné toute clé candidate K et tout attribut A qui n'est pas un constituant d'une clé candidate, A dépend de l'ensemble de K plutôt que d'une partie seulement.

Vous n'avez pas indiqué si l'année fait partie de la clé candidate ou non, mais je ne suis pas sûr que cela soit important, car dans les deux cas, 2NF serait satisfait en ce qui concerne l'année.

Sur le plan pratique, c'est une mauvaise idée de séparer l'année pour toutes les raisons que vous avez énumérées.

Leigh Riffel
la source
2

Je n'aime pas l'argument contre la table séparée en raison de sa taille ou du fait qu'elle contiendra des lignes inutilisées. Même si vous mettez 1000 ans dans ce tableau, la taille sera négligeable.

Cela dit, je ne pense pas que la table soit nécessaire. Quel est l'intérêt d'avoir un tableau séparé pour l'année? Ces données sont déjà dans la table principale et vous ne sauvez absolument rien en créant une deuxième table.

L'argument peut être différent pour une table de calendrier, où chaque ligne représente un jour et peut avoir d'autres attributs (jour de la semaine, décalage UTC, qu'il s'agisse d'un jour férié, etc.).

Mais l'année seule? Non, je ne vois aucun avantage du tout ... Et comme d'autres l'ont souligné, demandez-leur pourquoi ils pensent que c'est plus normalisé? Ou ce qu'ils gagnent? Si vous essayez d'écrire des requêtes comme

WHERE othertable.year = 2011

Au lieu de

WHERE dt >= 20110101 AND dt < 20120101

Ensuite, j'essaierais de vous convaincre que ce dernier est bien meilleur pour les performances (en supposant que dt est indexé) et le stockage. Si la simplicité du codage est primordiale, je dirais qu'une colonne calculée persistante serait meilleure qu'une autre table.

Aaron Bertrand
la source
1

Je suis totalement d'accord avec la réponse de Catcall, sauf sur un point: "l'année" n'est peut-être pas toujours une valeur primitive, mais je suppose que c'est plus un concept de logique métier que de conception de base de données.

En gardant le même design, supposons que les années ne devraient être que les années autorisées pour la publication. De cette manière, vous ne traitez pas avec des valeurs numériques primitives, mais plutôt un sous-ensemble d'entre elles, et comme ce sous-ensemble n'a pas d'implémentation primitive, vous devez faire votre propre (un tableau séparé?) Et le référencer (avec un FK). De cette manière, nous parlons encore d'années, mais nous devons les gérer d'une manière différente, car elles ont changé leur signification conceptuellement. Cependant, ils sont toujours "l'année de sortie", mais conceptuellement différents en termes de ce que cela signifie pour quelqu'un dans la connaissance du domaine.

Pour ce cas spécifique, je répète que la réponse de Catcall est correcte, mais je voulais juste le souligner. (Désolé, nous n'avons pas encore assez de représentants pour commenter.)

Alpha
la source