Estoy desarrollando una relación de amistad en MySQL donde la relación de amistad es mutua. Si A es amigo de B, entonces B es amigo de A. Si uno de los usuarios finaliza la amistad, la relación cae. Quiero aprender qué camino es mejor.
Tengo un sistema en ejecución;
user
-----------
userid p.k
name
friends
-------
userid
friendid
primary key (`userid`,`friendid`),
key `friendid` (`friendid`)
1 2
2 5
1 3
To get all of my friends;
SELECT u.name, f.friendid , IF(f.userid = $userid, f.friendid, f.userid) friendid
FROM friends f
inner join user u ON ( u.userid = IF(f.userid = $userid, f.friendid, f.userid))
WHERE ( f.userid = '$userid' or f.friendid = '$userid' )
Esta consulta funciona bien. Tal vez pueda agregar un UNION
. La consulta es más complicada que la siguiente y la tabla contiene la mitad de los registros que la siguiente.
Otra forma es mantener las relaciones en filas separadas;
1 2
2 1
2 5
5 2
1 3
3 1
SELECT u.name, f.friendid
FROM friends f inner join user u ON ( u.userid = f.friendid )
WHERE f.userid = '$userid'
Esta consulta es simple, aunque la tabla ocupa el doble de espacio.
Mi preocupación es; asumiendo que hay millones de usuarios; ¿De qué manera funcionará más rápido?
¿Cuáles son las ventajas y desventajas de ambas formas?
¿Qué debo tener en cuenta o cambiar por estas formas? ¿Y qué problemas puedo enfrentar en ambos sentidos?
fuente
Respuestas:
Lo primero que me llama la atención es la configuración del índice
friends
.Tienes esto en este momento:
Al realizar una verificación cruzada para la amistad mutua, podría incurrir en un pequeño gasto porque el ID de usuario puede recuperarse de la tabla al recorrer el
friendid
índice. Quizás podría indexar de la siguiente manera:Esto podría eliminar cualquier necesidad de acceder a la tabla y buscar solo en el índice.
Ahora, en términos de consultas, ambos pueden mejorar con el nuevo índice único. Crear el índice único también elimina la necesidad de insertar
(A,B)
y(B,A)
en la mesa porque(A,B)
, y(B,A)
sería el índice de todos modos. Por lo tanto, la segunda consulta no tendría que pasar por la tabla para ver si alguien es amigo de otra persona porque otra persona inició la amistad. De esa manera, si la amistad se rompe solo por una persona, no hay amistades huérfanas que sean unilaterales (parece mucho la vida en estos días, ¿no?)Parece que su primera consulta se beneficiaría más del índice único. Incluso con millones de filas, localizar amigos usando solo los índices evitaría tocar la mesa. Aún así, dado que no presentó una consulta UNION, me gustaría recomendar una consulta UNION:
Esto te permitirá ver quiénes son los amigos de cada ID de usuario.
Para ver todas las amistades, ejecuta esto:
Primero, aquí hay algunos datos de muestra:
Veamos todas las relaciones.
Veamos los 5 ID de usuario y veamos si las relaciones se muestran correctamente.
Todos me parecen correctos.
Ahora, usemos su segunda consulta para ver si coincide ...
¿Por qué no emparejar? Eso es porque no cargué el
(B,A)
para cada(A,B)
. Permíteme cargar las(B,A)
relaciones e intentar tu segunda consulta nuevamente.Todavía no coinciden. Eso es porque su segunda consulta solo está verificando un lado.
Verifiquemos su primera consulta con cada valor solo con (A, B) y no (B, A):
Tu primero funciona bien. Estoy seguro de que se está beneficiando del índice único, como dije antes, pero en mi humilde opinión, creo que la UNIÓN es más simple. Con un índice único, parecería ser seis de una docena y media del otro en términos de ejecución y salida.
Tendría que comparar su primera consulta con mi sugerencia UNION y ver.
Esta fue una buena pregunta que hizo hoy. +1 para tu pregunta.
fuente
friendid
,userid
) y ahora los resultados son aproximadamente .00794 ¿Es esto lo más rápido posible? Mirando los resultados, ¿crees que la primera forma es mejor (una fila para cada relación)? Porque es el doble de espacio que el segundo y los resultados son casi iguales con las configuraciones actuales.WHERE
,GROUP BY
yORDER BY
cláusulas como resultado que los datos se leen de un índice solamente. Aquí hay algunos buenos enlaces que justifican el uso de claves únicas y primarias como índices de cobertura: 1) peter-zaitsev.livejournal.com/6949.html , 2) mysqlperformanceblog.com/2006/11/23/… , 3) ronaldbradford .com / blog / tag / cover-index