Si A
es amigo de B
, ¿debería almacenar ambos valores AB
y BA
uno es suficiente? ¿Cuáles son las ventajas y desventajas de ambos métodos?
Aquí está mi observación:
- Si mantengo ambos, entonces tengo que actualizar ambos cuando recibo una solicitud de un amigo.
- Si no guardo ambos, entonces me resulta difícil tener que hacer múltiples
JOIN
con esta tabla.
Actualmente, mantengo la relación de una manera.
Entonces, ¿qué debo hacer en este caso? ¿Algún consejo?
mysql
relational-theory
Chan
fuente
fuente
mysql
que está almacenado en la nube de Amazon.Respuestas:
Almacenaría AB y BA. Una amistad es realmente una relación bidireccional, cada entidad está vinculada a otra. Aunque intuitivamente pensamos en la "amistad" como un vínculo entre dos personas, desde un punto de vista relacional es más como "A tiene un amigo B" y "B tiene un amigo A". Dos relaciones, dos registros.
fuente
Si la amistad tiene la intención de ser simétrica (es decir, no es posible
A
ser amigoB
pero no al revés), entonces simplemente almacenaría la relación unidireccional con una restricción de verificación para garantizar que cada relación solo se pueda representar de una manera.También abandonaría la identificación sustituta y tendría un PK compuesto en su lugar (y posiblemente un índice único compuesto también en las columnas invertidas).
No dice las consultas que esto dificulta, pero siempre puede crear una Vista
fuente
UNIQUE
para no poner una carga adicional innecesaria y redundante enINSERT
s? Como tenemosPRIMARY KEY (a,b)
y como es un PKUNIQUE
, lo inversoKEY (b,a)
también esUNIQUE
lo que sea.Suponiendo que una "amistad" siempre sea bidireccional / mutua, probablemente lo manejaría de esta manera.
El resultado es que lo cambia de una unión de muchos a muchos de "persona" a "persona", a una unión de muchos a muchos de "persona" a "amistad". Esto simplificará las uniones y restricciones, pero tiene el efecto secundario de permitir que más de dos personas en una sola "amistad" (aunque tal vez la flexibilidad adicional sería una ventaja potencial).
fuente
Es posible que deba definir índices en torno a las amistades en lugar de duplicar el número de filas:
De esta manera, duplica el almacenamiento para los índices pero no para los datos de la tabla. Como resultado, esto debería ser un ahorro del 25% en el espacio en disco. MySQL Query Optimizer elegirá realizar escaneos de rango de índice solamente, por eso el concepto de cubrir índices funciona bien aquí.
Aquí hay algunos enlaces agradables sobre los índices de cobertura:
ADVERTENCIA
Si la amistad no es mutua, tienes la base para otro tipo de relación: SEGUIR
Si friend_to no es amigo de friend_of, simplemente puede dejar esa relación fuera de la mesa.
Si desea definir relaciones para todos los tipos, sean mutuos o no, probablemente podría usar el siguiente diseño de tabla:
Desde la tabla de relaciones, puede organizar las relaciones para incluir lo siguiente:
Esto debería ser más robusto para todas las relaciones, ya sea que la relación sea mutua o no.
fuente
Si puede controlar dentro de la aplicación que la identificación de A siempre es menor que la identificación de B (ordene previamente los identificadores de los elementos A, B), puede aprovechar preguntar sin un OR (seleccione dónde id_A = a AND id_B = b, en lugar de preguntar (id_A = a AND id_B = b) OR (id_A = b AND id_B = a)), y también mantenga la mitad de los registros que necesitará con las aproximaciones del otro. Luego debe usar otro campo para mantener el estado de la relación (are-friends, a-solicited-to-b, b-solicited-to-a, exfriends-a, exfriends-b), y ya está.
Esta es la forma en que he administrado mi sistema de amistad, y esto simplifica el sistema y usa la mitad de las filas que necesitará con otros sistemas, solo diciendo que A es igual al valor de identificación más bajo en el código.
fuente