2010-09-10 12 views
10

Mi amigo y yo estamos construyendo un sitio web y tenemos un gran desacuerdo. El núcleo del sitio es una base de datos de comentarios sobre "personas". Básicamente, las personas pueden ingresar comentarios y pueden ingresar a la persona de quien se trata el comentario. Luego, los espectadores pueden buscar en la base de datos las palabras que están en el comentario o partes del nombre de la persona. Es completamente generado por el usuario. Por ejemplo, si alguien desea publicar un comentario en una versión mal escrita del nombre de una persona, puede hacerlo, y eso está bien. Por lo tanto, puede haber varias ortografías de diferentes personas enumeradas como varias entradas diferentes (algunas con segundo nombre, algunas con apodo, otras mal redactadas, etc.), pero todo está bien. No nos importa si las personas hacen comentarios sobre personas al azar o personas imaginarias.normalización innecesaria

De todos modos, el problema es cómo estamos estructurando la base de datos. En este momento es sólo una mesa con el ID de comentario como la clave principal, y luego hay un campo para la 'persona' el comentario es acerca de:

comentario ID - comentario - persona

1 - "él es raro" - John Smith

2 - "chica huele mal" - Jenny

3 - "gay" - John Smith

4 - "me debe $ 20" - Jennyyyyyyyyy

Todo funciona bien. Usando la base de datos, puedo crear páginas que enumeran todos los 'comentarios' para una 'persona' en particular. Sin embargo, está obsesionado con que la base de datos no esté normalizada. Leí acerca de la normalización y aprendí que estaba equivocado. La tabla ES actualmente normalizada, porque la ID del comentario es única y dicta el 'comentario' y la 'persona'. Ahora él es insistente en que 'la persona' debería tener su PROPIA mesa porque es una 'cosa'. No creo que sea necesario, porque aunque 'persona' realmente es el contenedor más grande (una 'persona' puede tener muchos 'comentarios' sobre ellos), la base de datos parece funcionar bien con 'persona' como un atributo de la identificación del comentario. Utilizo varias llamadas PHP para diferentes selecciones SQL para hacer que parezca mágicamente más sofisticado en la salida y la forma diferente en que el usuario puede buscar y ver los resultados, pero en realidad, la configuración es bastante simple. Ahora estoy permitiendo que los usuarios clasifiquen los comentarios con los pulgares arriba y con los pulgares hacia abajo, y conservo un 'puntaje' como otro campo en la misma tabla.

Creo que actualmente no es necesario tener una tabla separada para las entradas únicas de 'persona' porque las 'personas' no tienen su propia 'puntuación' o ninguno de sus propios atributos. Solo los comentarios lo hacen. Mi amigo es tan insistente que es necesario para la eficiencia. Finalmente dije, "OK, si quieres que cree una tabla separada y que 'persona' sea su propio campo, entonces ¿cuál sería el segundo campo? Porque si una tabla tiene solo una columna, parece inútil. Estoy de acuerdo que luego podemos crear la necesidad de darle a 'persona' su propia mesa, pero podemos ocuparnos de eso entonces ". Luego dijo que las cadenas no pueden ser claves primarias, y que convertiríamos las 'personas' en la tabla actual en números, y los números serían la clave principal en la nueva tabla 'persona'. Para mí, esto parece innecesario y haría que la tabla actual sea más difícil de leer. También piensa que será imposible crear la segunda tabla más adelante, y que debemos anticipar ahora que podríamos necesitarla para algo más adelante.

¿Quién tiene razón?

Respuesta

9

En mi opinión, tu amigo tiene razón.

La persona debe vivir en una mesa diferente y debe tratar de normalizar. No exageres, sin embargo.

A la larga, es posible que desee hacer más cosas con su sitio, digamos que desea adjuntar varios archivos a una persona (es decir.fotos) estarás muy agradecido por la normalización.

+0

Estoy de acuerdo con Frankie/su amigo. Hacer este tipo de cambio más tarde, aunque no es imposible, es incómodo y propenso a errores. – Jaydee

+2

¿Alguien puede explicar cómo la creación de una clave sustituta para un atributo que no aparece en el lado izquierdo de cualquier dependencia funcional normaliza una base de datos? Como dijo el OP, la Persona no determina nada (y nunca lo hará). ¿Habría ofrecido el mismo consejo para un atributo llamado 'Cosas'? Puede haber un problema de normalización aquí pero no involucra a la Persona. – NealB

+0

@NealB mi experiencia como docente y la forma en que se formula la pregunta me hacen creer que OP es parcial. El simple hecho de que el campo se llame persona y no texto es, IMO, relevante. – Frankie

3

Yo votaría por su amigo. Me gusta normalizar y planificar para el futuro e incluso si nunca lo necesita, esta normalización es tan fácil de hacer que, literalmente, no lleva tiempo. Puede crear una vista que consulte para hacer su SQL más limpio y eliminar la necesidad de que usted se una a las tablas usted mismo.

2

Si ya ha alcanzado todas sus capacidades y no tiene planes de ampliar las capacidades, creo que lo deja como está.

Si planea agregar más, es decir, permitir que las personas tengan cuentas, o cualquier cosa en realidad, creo que sería inteligente separar sus datos en las tablas Persona, Comentarios. No es difícil y facilita la expansión de su funcionalidad.

0

Aquí está el acuerdo. Cada vez que crees algo, quieres asegurarte de que tenga espacio para crecer. Desea intentar anticipar proyectos futuros y futuros avances para su programa. En este escenario, tiene razón al decir que actualmente no es necesario agregar una tabla de personas que solo contenga 1 campo (sin contar la ID, suponiendo que tiene un campo de ID int y un nombre de persona). Sin embargo, en el futuro, es posible que desee tener otros atributos para dichas personas, como nombre, apellido, dirección de correo electrónico, fecha de agregado, etc.

Si bien la sobrenormalización es ciertamente perjudicial, personalmente crearía otra, una tabla más grande para contener a la persona con campos adicionales para que pueda agregar fácilmente nuevas características en el futuro.

+1

¿Es realmente tan difícil en un momento posterior simplemente extraer todas las entradas 'únicas' de 'persona' y convertirlas en una columna en una nueva tabla? y hay un problema con el uso de una cadena como clave principal? –

+1

Usar una cuerda como tu PK solo hace las cosas más difíciles. La gran cantidad de DBMS le permite usar identificadores numéricos de auto incremento, por lo que no necesita preocuparse por la posibilidad de que ocurra un error. Simplemente tiene más sentido tener una ID numérica que una cadena. – Aaron

1

Bueno, hay dos escuelas de pensamiento. Una dice: crea tu modelo de datos de la manera más normalizada posible, luego des-normaliza si necesitas más eficiencia. El otro es básicamente "hacer el trabajo mínimo necesario para el trabajo, luego cambiarlo a medida que cambien sus requisitos". También conocido como YAGNI (No lo va a necesitar).

Todo depende de dónde vea esto. Si esto es todo lo que será, entonces su enfoque probablemente esté bien. Si intenta mejorarlo con nuevas características con el tiempo, entonces su amigo tiene razón.

2

Tienes razón.

Person puede ser una cosa en general, pero no en su modelo. Si fuera a molestar a las personas para que identifiquen correctamente a la persona de la que están hablando, sería necesaria una tabla Person. Por ejemplo, si los comentarios fueron solo sobre personas ya registradas en la base de datos.

Pero aquí parece que tiene datos desestructurados, sin identidad; y que nada/nadie está interesado en asegurarse de si "jenny" y "jennyyy" son de hecho la misma persona, sin mencionar "jenny doe", y "mi primo" ...

7

Creando una nueva tabla para persona y el uso de la clave de esa tabla en lugar del atributo persona no tiene nada que ver con la normalización. Puede ser una buena idea por otras razones, pero hacerlo no hace que la base de datos esté "más normalizada" que no hacerlo. Así que tienes razón: en lo que respecta a la normalización, no es necesario crear otra tabla.

1

La normalización tiene que ver con las dependencias funcionales (FD). Debe identificar todos de FD que existen entre los atributos de su modelo de datos antes de que pueda ser completamente normalizado.

Vamos a revisar lo que tiene:

  • cualquier caso dado de un CommentId determina funcionalmente la Person (FD: CommentId ->Person)
  • cualquier caso dado de un CommentId determina funcionalmente la Comment (FD: CommentId ->Comment)
  • Cualquier instancia determinada de CommentId determina funcionalmente el UserId (FD: CommentId ->UserId)
  • cualquier caso dado de un CommentId determina funcionalmente la Score (FD: CommentId ->Score)

Todo aquí es un atributo dependiente de CommentId y CommentId solo. Esto podría llevarlo a la creencia de que una relación (tabla) que contenga todo, o un subconjunto de, los atributos anteriores de debe estar normalizada.

Lo primero que debe preguntarse es ¿por qué creó el atributo CommentId de todos modos? Estrictamente hablando, este es un atributo fabricado - no se relaciona con nada 'real'. CommentId es comúnmente se conoce como clave sustituta. Una clave sustituta es solo un valor inventado que se encuentra en para un conjunto de valores únicos que corresponde a algún otro grupo de atributos. Entonces, ¿para qué grupo de atributos es CommentId un sustituto? Podemos cifra que a cabo haciendo las siguientes preguntas y añadiendo nuevas de FD al modelo:

  • 1) ¿Tiene un comentario tienen que ser únicos? Si es así, el FD: Comment ->CommentId debe ser verdadero.
  • 2) ¿Se puede hacer el mismo comentario varias veces siempre que se trate de una persona diferente? Si es así, entonces FD: Person + Comment ->CommentId debe ser verdadero y el FD en 1 de arriba es falso.
  • 3) ¿Se puede hacer el mismo comentario varias veces sobre la misma persona, siempre que haya sido hecha por UserId's diferentes? Si es así, los FD en 1 y 2 no pueden ser verdaderos, pero FD: Person + Comment + UserId ->CommentId puede ser verdadero.
  • 4) ¿Se puede hacer el mismo comentario varias veces sobre la misma persona por el mismo ID de usuario pero tiene puntuaciones diferentes? Esto implica FD: Person + Comment + UserId '+ Score ->CommentId es verdadero y los otros son falsos.

Exactamente uno de los anteriores 4 FD anteriores debe ser cierto. Cualquiera que sea, afecta cómo se normaliza su modelo de datos.

FD Supongamos: Person + + CommentUserId ->CommentId resulta ser cierto.Las lógicas consecuencias son que:

  • Person + Comment + UserId y CommentId sirven como teclas equivalentes con respecto a Score
  • Score debe ser puesto en una relación con uno pero no ambos de sus teclas (para evitar transitiva dependencias). La opción obvia sería CommentId ya que se creó específicamente como sustituto.
  • Una relación compuesta de: CommentId, Person, Comment, se necesita UserId para atar el Key a su sustituto.

Desde un punto de vista teórico, la clave sustituta CommentId no se requiere para hacer su modelo de datos o el trabajo de base de datos. Sin embargo, su presencia puede afectar cómo se construyen las relaciones.

La creación de claves sustitutivas es un tema práctico de cierta importancia. Considere lo que podría pasar si decide no utilizar una clave sustituta pero el atributo Sistema completo de Person + Comment + UserId en su lugar, sobre todo si se requiere en múltiples tablas como una clave externa o primaria:

  • El comentario puede agregar una gran cantidad de espacio por encima a su base de datos porque se repite en varias tablas. Probablemente es más que un par de caracteres de largo.
  • ¿Qué sucede si alguien elige editar un comentario? Ese cambio debe propagarse a todas las tablas donde Comment es parte de una clave. No es una bonita vista!
  • Indexación llaves largos y complejos pueden tomar una gran cantidad de espacio y/o hacer para obtener un rendimiento de actualización lenta

El valor asignado a una clave sustituta nunca cambia, no importa lo que haces a los valores asociados a los atributos que determina La actualización de los atributos dependientes ahora es limitada a la única tabla que define la clave sustituta. Esto es de gran importancia práctica.

Ahora, de nuevo a si debe crear un sustituto para Person. ¿Person vive en el lado izquierdo de muchos, o cualquiera, FD? Si lo hace, su valor se propagará a través de su base de datos y existe la posibilidad de crear un sustituto para él. Si la persona es un atributo numérico o de texto es irrelevante para la opción de crear una clave sustituta.

Según lo que ha dicho, hay en el mejor de los casos un argumento débil para crear un sustituto para Person. Este argumento se basa en la sospecha de que su valor puede convertirse en algún momento en una clave o parte de una clave en algún momento en el futuro.

1

Si nunca tiene la intención de asociar la columna de persona con un usuario o cualquier otra cosa y aparentemente los datos no necesitan constancia ni comprobaciones de integridad de datos, ¿por qué está esto en una base de datos relacional? ¿No sería este un caso de uso para una base de datos nosql? ¿O me estoy perdiendo algo?

0

Cuando se trata de usuarios, debe haber una tabla dedicada.Luego puede unir las tablas y referirse a la ID de ese usuario.

user -> id | username | password | email 

comment -> id | user_id | content 

SQL para unirse a los comentarios de los usuarios:

SELECT user.username, comment.content FROM user JOIN comment WHERE user.id = comment.user_id; 

Se va a hacer que sea mucho más fácil en el futuro cuando se quiere encontrar información sobre ese usuario específico. La cantidad de esfuerzo extra es insignificante.

En cuanto al "puntaje" para cada comentario, también debería ser una tabla separada. De esta forma, puede conectar a un usuario a "me gusta" o "no me gusta".

0

Con esta base de datos, es posible que sienta que está bien, pero puede haber algún problema en el futuro cuando desee que los usuarios sepan más de la base de datos. Supongamos que desea saber la cantidad de comentarios realizados sobre una persona con el nombre = 'abc'. En este caso, deberá pasar por la tabla completa de comentarios y seguir contando. En lugar de esto, puede tener un atributo llamado 'conteo' para cada persona e incrementarlo cada vez que un comentario está hecho en esa persona.
En cuanto a la normalización, siempre es mejor tener una base de datos normalizada porque reduce la redundancia y hace que la base de datos sea intuitiva. Si espera que su base de datos crezca en el futuro, entonces la normalización debe estar presente.