Version corta
Tengo que agregar un número fijo de propiedades adicionales a cada par en una unión de muchos a muchos existente. Saltando a los diagramas a continuación, ¿cuál de las Opciones 1-4 es la mejor manera, en términos de ventajas y desventajas, de lograr esto extendiendo el Caso Base? ¿O hay una alternativa mejor que no haya considerado aquí?
Versión más larga
Actualmente tengo dos tablas en una relación de muchos a muchos, a través de una tabla de unión intermedia. Ahora necesito agregar enlaces adicionales a propiedades que pertenecen al par de objetos existentes. Tengo un número fijo de estas propiedades para cada par, aunque una entrada en la tabla de propiedades puede aplicarse a varios pares (o incluso puede usarse varias veces para un par). Estoy tratando de determinar la mejor manera de hacer esto, y estoy teniendo problemas para resolver cómo pensar en la situación. Semánticamente parece que puedo describirlo como cualquiera de los siguientes igualmente bien:
- Un par vinculado a un conjunto de un número fijo de propiedades adicionales
- Un par vinculado a muchas propiedades adicionales
- Muchos (dos) objetos vinculados a un conjunto de propiedades
- Muchos objetos vinculados a muchas propiedades.
Ejemplo
Tengo dos tipos de objetos, X e Y, cada uno con ID únicos, y una tabla de enlace objx_objy
con columnas x_id
y y_id
, que juntas forman la clave principal para el enlace. Cada X se puede relacionar con muchas Y, y viceversa. Esta es la configuración de mi relación existente de muchos a muchos.
Caso base
Ahora, además, tengo un conjunto de propiedades definidas en otra tabla, y un conjunto de condiciones bajo las cuales un par dado (X, Y) debe tener la propiedad P. El número de condiciones es fijo, y lo mismo para todos los pares. Básicamente dicen "En la situación C1, el par (X1, Y1) tiene la propiedad P1", "En la situación C2, el par (X1, Y1) tiene la propiedad P2", y así sucesivamente, para tres situaciones / condiciones para cada par en la unión mesa.
Opción 1
En mi situación actual hay exactamente tres de estas condiciones, y no tengo ninguna razón para esperar que para aumentar, por lo que una posibilidad es añadir columnas c1_p_id
, c2_p_id
y c3_p_id
que featx_featy
, especificando para un determinado x_id
y y_id
, que la propiedad p_id
de uso en cada uno de los tres casos .
Esto no me parece una gran idea, porque complica el SQL para seleccionar todas las propiedades aplicadas a una característica, y no escala fácilmente a más condiciones. Sin embargo, impone el requisito de un cierto número de condiciones por par (X, Y). De hecho, es la única opción aquí que lo hace.
opcion 2
Cree una tabla de condiciones cond
y agregue la ID de condición a la clave principal de la tabla de unión.
Una desventaja de esto es que no especifica el número de condiciones para cada par. Otra es que cuando solo estoy considerando la relación inicial, con algo como
SELECT objx.*, objy.* FROM objx
INNER JOIN objx_objy ON objx_objy.x_id = objx.id
INNER JOIN objy ON objy.id = objx_objy.y_id
Luego tengo que agregar una DISTINCT
cláusula para evitar entradas duplicadas. Esto parece haber perdido el hecho de que cada par debería existir solo una vez.
Opción 3
Cree una nueva 'ID de par' en la tabla de unión, y luego tenga una segunda tabla de enlaces entre la primera y las propiedades y condiciones.
Esto parece tener la menor cantidad de desventajas, además de la falta de imposición de un número fijo de condiciones para cada par. Sin embargo, ¿tiene sentido crear una nueva ID que identifique nada más que las ID existentes?
Opción 4 (3b)
Básicamente lo mismo que la Opción 3, pero sin la creación del campo ID adicional. Esto se logra poniendo ambas identificaciones originales en la nueva tabla de unión, por lo que contiene x_id
y y_id
campos, en lugar de xy_id
.
Una ventaja adicional de este formulario es que no altera las tablas existentes (aunque todavía no están en producción). Sin embargo, básicamente duplica una tabla completa varias veces (o se siente así, de todos modos), por lo que tampoco parece ideal.
Resumen
Mi sensación es que las opciones 3 y 4 son lo suficientemente similares como para que yo pueda elegir cualquiera de ellas. Probablemente ya lo hubiera hecho si no fuera por el requisito de un número pequeño y fijo de enlaces a propiedades, lo que hace que la Opción 1 parezca más razonable de lo que sería de otra manera. Según algunas pruebas muy limitadas, agregar una DISTINCT
cláusula a mis consultas no parece afectar el rendimiento en esta situación, pero no estoy seguro de que la Opción 2 represente la situación tan bien como a las demás, debido a la duplicación inherente causada por la colocación los mismos pares (X, Y) en varias filas de la tabla de enlaces.
¿Es una de estas opciones mi mejor camino a seguir, o hay otra estructura que debería considerar?
fuente
DISTINCT
cláusula, que estaba pensando en una consulta como la que al final del # 2, que unex
yy
a través dexyc
, pero no se refiere ac
... Así que si he(x_id, y_id, c_id)
limitadoUNIQUE
con filas(1,1,1)
y(1,1,2)
, a continuaciónSELECT x.id, y.id FROM x JOIN xyc JOIN y
, voy a volver dos idénticos filas(1,1)
, y(1,1)
.Respuestas:
Opción 1
No necesariamente complica la consulta SQL (vea la conclusión a continuación).
Se escala fácilmente a más condiciones, siempre que haya un número fijo de condiciones y no haya docenas o cientos.
Lo hace, y aunque usted dice en un comentario que este es "el menos importante de mis requisitos", no ha dicho que no importa en absoluto.
opcion 2Creo que puede descartar esta opción debido a las complicaciones que menciona. La
objx_objy
tabla es probable que sea la mesa de conducción para algunos de sus consultas (por ejemplo, "seleccionar todas las propiedades aplicadas a una función", que estoy tomando el sentido de todas las propiedades aplicadas a unaobjx
oobjy
). Puede usar una vista para preaplicar, porDISTINCT
lo que no es una cuestión de complicar las consultas, pero eso va a escalar muy mal en términos de rendimiento para muy poca ganancia.Opción 3No, no lo hace: la opción 4 es mejor en todos los aspectos.
Opcion 4
Esta opción está bien: es la forma obvia de establecer las relaciones si el número de propiedades es variable o está sujeto a cambios
Conclusión
Mi preferencia sería la opción 1 si
objx_objy
es probable que el número de propiedades sea estable, y si no puede imaginar agregar más que un puñado extra. También es la única opción que impone la restricción 'número de propiedades = 3'; aplicar una restricción similar en la opción 4 probablemente implicaría agregarc1_p_id
... columnas a la tabla xy de todos modos *.Si realmente no le importa mucho esa condición, y también tiene razones para dudar de que la condición del número de propiedades será estable, elija la opción 4.
Si no está seguro de cuál, elija la opción 1: es más simple y definitivamente es mejor si tiene la opción, como han dicho otros. Si se pospone la opción 1 "... porque complica el SQL para seleccionar todas las propiedades aplicadas a una característica ..." Sugiero crear una vista para proporcionar los mismos datos que la tabla adicional en la opción 4:
Opción 1 tablas:
ver para 'emular' la opción 4:
"seleccionar todas las propiedades aplicadas a una característica":
dbfiddle aquí
fuente
Creo que cualquiera de estas opciones podría funcionar, pero elegiría la opción 1 si el número de condiciones es realmente fijo en 3, y la opción 2 si no lo es. La navaja de Occam también funciona para el diseño de bases de datos, siendo todos los demás factores iguales, el diseño más simple suele ser el mejor.
Aunque si desea seguir reglas estrictas de normalización de la base de datos, creo que necesitaría ir con 2 independientemente de si el número de condiciones es fijo.
fuente