Normalización: ¿se considera compatible dividir valores numéricos estáticos como un año en su propia tabla?


16

Estoy teniendo una discusión interesante con otro diseñador de bases de datos sobre la normalización. En este ejemplo, tenemos una tabla de GameTitles y cada registro debe contener el año en que se lanzó el juego. Él dice que 2NF exige que todo debe normalizarse, por lo tanto, para cumplir, el campo del año debe dividirse en una tabla ReleaseYears con su propia clave principal a la que hace referencia la tabla GameTitles. Digo que debería permanecer como un campo en la tabla GameTitles.

Mi argumento para esto es que un año es solo un valor numérico no primitivo que es estático por su propia naturaleza (es decir, 2011 siempre será 2011). Debido a esto, sirve como su propio identificador y no necesita nada para referenciarlo, ya que es lo que es. Esto también introduce mantenimiento adicional, ya que ahora debe agregar un nuevo año a la tabla solo para referenciarlo. Si rellena previamente la tabla con una amplia gama de años, entonces tiene registros adicionales que potencialmente no tendrán referencias a ellos en absoluto. Esto también aumenta el tamaño de la base de datos, ya que ahora tiene una tabla adicional, gastos generales de registro y la clave primaria adicional para el año en sí. Si mantiene el año como un campo en la tabla GameTitles, eliminará todo este mantenimiento adicional y gastos generales.

¿Pensamientos sobre esto?

editar: destinado a publicar esto en StackOverflow. ¿Alguien puede votar para eliminar esto o marcarlo para llamar la atención?


66
¿Porque? Parece que encaja bien aquí.
Leigh Riffel

La pregunta que quiero hacer es si está preguntando esto sobre la normalización o las necesidades reales de producción. Para la producción, preguntaría si eso es algo válido.
jcolebrand

Respuestas:


14

El otro diseñador de bases de datos simplemente está equivocado, pero su razonamiento también está equivocado. Suponga que comienza con esta tabla, que tiene una sola clave candidata, "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

Usted evalúa si está en 2NF haciéndose estas preguntas.

Q: En primer lugar, es en 1NF?

R: Sí, lo es.

P: ¿Cuáles son los atributos principales (atributos que forman parte de una clave candidata)?

R: "GAME_TITLE" es el atributo único primer.

Q: ¿Cuáles son los atributos que no son primos?

A: "year_first_released" es el único.

Q: ¿Es "year_first_released" funcionalmente dependiente de la totalidad de "GAME_TITLE", o en sólo una parte de ella?

R: La única clave candidata, "game_title", es una sola columna; Ni siquiera tiene partes. Por lo tanto, "year_first_released" depende funcionalmente del conjunto de "game_title".

Voilà. Has encontrado 2NF.

Puede cortar algunos de los términos formales preguntando primero si está en 1NF y luego respondiendo esta pregunta.

P: ¿Hay claves candidatas compuestas?

A: no.

Voilà. Has encontrado 2NF de nuevo.

Por definición, para que una tabla viole 2NF, debe tener al menos una clave candidata que tenga más de una columna.

Aquí están sus razones para rechazar la opinión de su amigo.

  • Un año es solo un valor numérico no primitivo.
  • Un año es estático por su propia naturaleza.
  • Un año sirve como su propio identificador.
  • Una tabla de años introduce mantenimiento adicional.
  • Una tabla de años puede tener filas adicionales a las que no se hace referencia.
  • Una tabla de años aumenta el tamaño de la base de datos.

Ninguna de estas razones tiene nada que ver con si una tabla está en 2NF.

Al diseñar una base de datos, no está mal considerar los problemas de mantenimiento, el tamaño de la base de datos, las filas sin referencia, las restricciones de rango, etc. Es simplemente incorrecto llamar a esas cosas normalización.

Ah, y esa tabla de dos columnas que proporcioné arriba, está en 5NF.


2
Bien hecho. Estuve tentado de publicar una respuesta que decía nada más que tu primera oración ... "El otro diseñador de bases de datos simplemente está equivocado", has cubierto muy bien el por qué.
Mark Storey-Smith

5

Crear una tabla separada para cualquier atributo no tiene nada que ver con la normalización. 2NF, 3NF, BCNF, 4NF, 5NF se preocupan por eliminar las dependencias no clave. Si elimina cualquier atributo individual a una nueva tabla y lo reemplaza con un atributo de clave externa, entonces las dependencias en la tabla serán lógicamente las mismas que antes, por lo que la versión revisada de la tabla no está más o menos normalizada de lo que está. Fue antes.


Quiero agregar algo a esto, pero no estoy seguro de qué. Está diciendo que mover algo a una tabla que tiene una correlación 1: 1 (ya sea 1 clave para exactamente 1 valor como en este caso, o una fila a una fila) no da ningún beneficio si la búsqueda no es necesaria, ¿verdad? Pero existe un beneficio potencial de búsqueda si rara vez necesita el año y solo está buscando un rango de 255 años o menos. Posiblemente podría salirse con algunos bytes guardados aquí, pero dado que normalmente se asignan a 4bytes de todos modos, esta no es una suposición razonable.
jcolebrand

1
@jcolebrand: De acuerdo con lo que dices. Aún así, la respuesta a la pregunta es la misma: si lo haces o no no tiene nada que ver con la normalización per se.
nvogel

Estoy de acuerdo. Como dije, el mío era un poco entusiasta "Siento que al OP le falta algo aquí" ... porque no estoy seguro de dónde ir con ese concepto.
jcolebrand

5

Desde mi punto de vista, una tabla de años separada solo tendría sentido si el "año de publicación" no es un año calendario, sino, por ejemplo, un año fiscal que podría abarcar varios años calendario (por ejemplo, de octubre a octubre).

Esa tabla mantendría la definición (fecha real de inicio y finalización) del año fiscal


1
+1 solo necesitas una tabla si va a tener atributos :)
Jack Douglas

2

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

una tabla 1NF está en 2NF si y solo si, dada cualquier clave candidata K y cualquier atributo A que no sea un componente de una clave candidata, A depende de la totalidad de K en lugar de solo una parte de ella.

No indicó si el año es parte de la clave del candidato o no, pero no estoy seguro de que importe, porque en cualquier caso 2NF estaría satisfecho en lo que respecta al año.

A nivel práctico, es una mala idea separar el año por todas las razones que mencionó.


2

No me gusta el argumento en contra de la tabla separada debido a su tamaño o que tendrá filas no utilizadas. Incluso si pones 1000 años en esta tabla, el tamaño será insignificante.

Dicho esto, no creo que la mesa sea necesaria en absoluto. ¿Cuál es el punto de tener una mesa separada para el año? Estos datos ya están en la tabla principal y no guarda absolutamente nada al crear una segunda tabla.

El argumento puede ser diferente para una tabla de calendario, donde cada fila representa un día y puede tener otros atributos (día de la semana, desplazamiento UTC, ya sea un día festivo, etc.).

Pero año solo? No, no veo ningún beneficio en absoluto ... Y como otros han señalado, pregúntales por qué piensan que eso es más normalizado. O lo que ganan? Si intentas escribir consultas como

WHERE othertable.year = 2011

En lugar de

WHERE dt >= 20110101 AND dt < 20120101

Entonces trataría de persuadirlo de que este último es mucho mejor para el rendimiento (suponiendo que dt esté indexado) y el almacenamiento. Si la simplicidad de codificación es primordial, diría que una columna calculada persistente sería mejor que otra tabla.


1

Estoy totalmente de acuerdo con la respuesta de Catcall, excepto en un punto: "año" puede no ser siempre un valor primitivo, pero supongo que es más un concepto de lógica de negocios que un diseño de base de datos.

Manteniendo el mismo diseño, supongamos que los años solo deberían ser aquellos años que están permitidos para su lanzamiento. De esta manera, no está tratando con valores numéricos primitivos, sino con un subconjunto de ellos, y como tal subconjunto no tiene una implementación primitiva, debe hacer lo suyo (¿una tabla separada?) Y hacer referencia a él (con un FK). De esa manera, todavía estamos hablando de años, pero necesitamos administrarlos de una manera diferente, porque conceptualmente cambiaron su significado. Sin embargo, todavía son "año de lanzamiento", pero conceptualmente diferentes en términos de lo que significan para alguien en el dominio del conocimiento.

Para este caso específico, nuevamente digo que la respuesta de Catcall es correcta, pero solo quería señalarlo. (Lo siento, todavía no tengo suficiente representante para comentar).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.