Pregunta

Tengo las siguientes tablas en mi base de datos que tienen una relación de muchos a muchos, que se expresa mediante una tabla de conexión que tiene claves externas a las claves primarias de cada una de las tablas principales:

  • Reproductor:WidgetID (PK), título, precio
  • Usuario:ID de usuario (PK), nombre, apellido

Supongamos que cada combinación de usuario-widget es única.Puedo ver dos opciones sobre cómo estructurar la tabla de conexión que define la relación de datos:

  1. Widgets de usuario1:ID de widget de usuario (PK), ID de widget (FK), ID de usuario (FK)
  2. Widgets de usuario2:ID de widget (PK, FK), ID de usuario (PK, FK)

La opción 1 tiene una sola columna para la clave principal.Sin embargo, esto parece innecesario ya que los únicos datos que se almacenan en la tabla son la relación entre las dos tablas principales, y esta relación en sí misma puede formar una clave única.Esto lleva a la opción 2, que tiene una clave primaria de dos columnas, pero pierde el identificador único de una columna que tiene la opción 1.Opcionalmente, también podría agregar un índice único de dos columnas (WidgetID, UserID) a la primera tabla.

¿Existe alguna diferencia real entre los dos en cuanto a rendimiento, o alguna razón para preferir un enfoque sobre el otro para estructurar la tabla de muchos a muchos de UserWidgets?

¿Fue útil?

Solución

Sólo tienes una clave principal en cualquier caso.La segunda es lo que se llama clave compuesta.No hay ninguna buena razón para introducir una nueva columna.En la práctica, deberá mantener un índice único en todas las claves candidatas.Agregar una nueva columna no le genera nada más que gastos generales de mantenimiento.

Vaya con la opción 2.

Otros consejos

Personalmente yo haría tener la columna de clave sintética/sustituta en tablas de muchos a muchos por los siguientes motivos:

  • Si ha utilizado claves sintéticas numéricas en las tablas de su entidad, tener las mismas en las tablas de relaciones mantiene la coherencia en el diseño y la convención de nomenclatura.
  • Puede darse el caso en el futuro de que la propia tabla de muchos a muchos se convierta en una entidad principal de una entidad subordinada que necesite una referencia única a una fila individual.
  • Realmente no va a utilizar tanto espacio adicional en disco.

La clave sintética no reemplaza a la clave natural/compuesta ni se convierte en la PRIMARY KEY para esa tabla solo porque es la primera columna de la tabla, por lo que estoy parcialmente de acuerdo con el artículo de Josh Berkus.Sin embargo, no estoy de acuerdo con que las claves naturales sean siempre buenas candidatas para PRIMARY KEY's y ciertamente no deben usarse si se van a usar como claves externas en otras tablas.

La opción 2 usa una clave compuesta simple, la opción 1 usa una clave sustituta.La opción 2 es la preferida en la mayoría de los escenarios y se acerca al modelo realista en el sentido de que es una buena clave candidata.

Hay situaciones en las que es posible que desee utilizar una clave sustituta (Opción 1)

  1. No es que la clave compuesta sea una buena clave candidata a lo largo del tiempo.Particularmente con datos temporales (datos que cambian con el tiempo).¿Qué pasaría si quisiera agregar otra fila a la tabla UserWidget con el mismo UserId y WidgetId?Piense en Empleo (EmployeeId,EmployeeId): funcionaría en la mayoría de los casos, excepto si alguien volviera a trabajar para el mismo empleador en una fecha posterior.
  2. Si está creando mensajes/transacciones comerciales o algo similar que requiere una clave más fácil de usar para la integración.¿Replicación tal vez?
  3. Si desea crear sus propios mecanismos de auditoría (o similares) y no quiere que las claves sean demasiado largas.

Como regla general, al modelar datos encontrará que la mayoría de las entidades asociativas (muchas a muchas) son el resultado de un evento.La persona acepta un empleo, el artículo se agrega a la cesta, etc.La mayoría de los eventos tienen una dependencia temporal del evento, donde la fecha o la hora son relevantes, en cuyo caso una clave sustituta puede ser la mejor alternativa.

Entonces, elige la opción 2, pero asegúrate de tener el modelo completo.

Estoy de acuerdo con las respuestas anteriores pero tengo una observación que agregar.Si desea agregar más información a la relación y permitir más relaciones entre las mismas dos entidades, necesita la opción uno.

Por ejemplo, si desea realizar un seguimiento de todas las veces que el usuario 1 ha utilizado el widget 664 en la tabla de widgets de usuario, el ID de usuario y el ID del widget ya no son únicos.

¿Cuál es el beneficio de una clave primaria en este escenario?Considere la opción sin clave principal:Widgets de usuario3:ID de widget (FK), ID de usuario (FK)

Si desea unicidad, utilice la clave compuesta (UserWidgets2) o una restricción de unicidad.

La ventaja de rendimiento habitual de tener una clave principal es que a menudo se consulta la tabla mediante la clave principal, lo cual es rápido.En el caso de tablas de muchos a muchos, normalmente no se consulta mediante la clave principal, por lo que no hay ningún beneficio en el rendimiento.Las tablas de muchos a muchos se consultan mediante sus claves externas, por lo que debería considerar agregar índices en WidgetID y UserID.

La opción 2 es la respuesta correcta, a menos que tenga una muy buena razón para agregar una clave numérica sustituta (lo que hizo en la opción 1).

Las columnas de claves numéricas sustitutas no son "claves principales".Las claves primarias son técnicamente una combinación de columnas que identifican de forma única un registro dentro de una tabla.

Cualquiera que cree una base de datos debería leer este artículo. http://it.toolbox.com/blogs/database-soup/primary-keyvil-part-i-7327 por Josh Berkus para comprender la diferencia entre columnas de claves numéricas sustitutas y claves primarias.

En mi experiencia, la única razón real para agregar una clave numérica sustituta a su tabla es si su clave principal es una clave compuesta y debe usarse como referencia de clave externa en otra tabla.Sólo entonces deberías pensar en agregar una columna adicional a la tabla.

Siempre que veo una estructura de base de datos donde cada tabla tiene una columna 'id', lo más probable es que haya sido diseñada por alguien que no aprecia el modelo relacional e invariablemente mostrará uno o más de los problemas identificados en el artículo de Josh.

Yo iría con ambos.

Escúchame:

La clave compuesta es obviamente la forma agradable y correcta de hacerlo en lo que respecta a reflejar el significado de sus datos.No hay duda.

Sin embargo:He tenido todo tipo de problemas para que la hibernación funcione correctamente a menos que uses una única clave primaria generada: una clave sustituta.

Entonces usaría datos lógicos y físicos. modelo.El lógico tiene la clave compuesta.El modelo físico, que implementa el modelo lógico, tiene la clave sustituta y las claves externas.

Dado que cada combinación de usuario-widget es única, debe representarla en su tabla haciendo que la combinación sea única.En otras palabras, opta por la opción 2.De lo contrario, es posible que tenga dos entradas con el mismo widget y ID de usuario, pero diferentes ID de widget de usuario.

El userwidgetid en la primera tabla no es necesario, como usted dijo, la unicidad proviene de la combinación del widgetid y el userid.

Usaría la segunda tabla, mantendría las claves externas y agregaría un índice único en widgetid y userid.

Entonces:

userwidgets( widgetid(fk), userid(fk),
             unique_index(widgetid, userid)
)

Hay cierta mejora en el rendimiento al no tener la clave primaria adicional, ya que la base de datos no necesitaría calcular el índice de la clave.En el modelo anterior, aunque este índice (a través del índice_único) todavía se calcula, pero creo que esto es más fácil de entender.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top