2012-01-20 15 views
5

Necesito hacer un seguimiento de los usuarios que están en línea en mi sitio para que pueda mostrar un icono "en línea" al lado de los avatares de los usuarios que están en línea.¿Por qué mi consulta MySQL es rápida cuando lo hago de esta manera y lento cuando lo hago de esta manera?

La primera etapa de detectar esto es mantener un registro de cuando el usuario fue visto por última vez por lo que estoy haciendo una consulta UPDATE cada vez que el usuario solicita una página:

UPDATE `users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

Ahora justo después de esto, ejecutar otra consulta, ésta se lleva todos los usuarios de mi sitio bajo cierto criterio para que pueda mostrarlos en la página de inicio:

SELECT *, 
(ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) AS SearchRadius 
FROM `users` 
INNER JOIN `profiles` ON (
    users.user_id = profiles.user_id 
) 
WHERE (users.latitude > 38.904216788163 AND users.latitude < 42.501503211837) 
AND (users.longitude > -76.252301637251 AND users.longitude < -71.507178362749) 
AND (ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) < 200 AND users.sex = '1' AND users.seeking = '2' AND users.user_id != '1' AND users.account_status = '1' LIMIT 0, 10 

No importa la locura de esta consulta, básicamente, el punto es que estoy seleccionando desde el mismo users tabla que estaba actualizando previamente En g.

Cuando ejecuto estas 2 preguntas, uno tras otro estos son los tiempos que recibo:

1st query: 0.0392 seconds 
2nd query: 1.5396 seconds 

esto causa un retraso significativo en el tiempo de carga.

Ahora, cuando he creado una tabla separada para usuarios y cambiar la primera consulta a este:

UPDATE `online_users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

Los tiempos cambiaron a esto:

1st query: 0.0411 seconds 
2nd query: 0.0008 seconds 

y la página se carga mucho más rápido!

¿Por qué es esto? Supongo que tiene algo que ver con el bloqueo de la mesa, pero no sé lo suficiente como para estar seguro o saber más detalles.

+0

¿La segunda consulta sigue arrojando los resultados correctos? –

+1

Si ejecuta la segunda consulta sin el primero, ¿es más rápido? Podría ser algún tipo de problema de E/S: no estoy al tanto de las funciones internas de MySQL, pero ese no debería ser el tipo de bloqueo en el sentido SQL, después de todo, está en la misma conexión en la misma transacción, en ese caso, está permitido ver cambios no confirmados o los cambios ya están confirmados. ¿Estás usando InnoDB o MyISAM? –

+0

@Cade Roux Si ejecuto solo la segunda consulta, es más rápido pero solo en un minuto en 0.0004. Estoy usando MyISAM. – TK123

Respuesta

1

Porque SELECT * incluye last_seen MySQL no puede almacenar en caché la consulta o subconsultas. Puede intentar una enumeración explícita de todos los campos, excepto last_seen.

(Pero una tabla separada online_users tiene mucho sentido.)

+0

acaba de probarlo con una llamada explícita a todos los nombres de columna, excepto last_seen y el tiempo de consulta todavía era la misma longitud. – TK123

+0

Así que somos más sabios; simplemente al actualizar la misma tabla, se eliminan _todos los datos de consulta en caché de esa tabla. O algo oscuro como la asignación de subprocesos por tabla y la recuperación de disco de la actualización. –

-4

consulta en tabla InnoDB es más lento que en MyISAM. más filas en la tabla hacen que la consulta sea más lenta. la indexación incorrecta en la tabla hace que la consulta sea más lenta, verifique con el comando EXPLAIN.

0

Suponiendo que la consulta SELECT se ejecuta varias veces antes de la prueba, es probable que vea los efectos de la caché de consultas. Cualquier actualización en la tabla invalidará la caché y forzará que la consulta se ejecute de nuevo. Al actualizar una tabla diferente, estás evitando bloquear esas entradas de caché.

+0

esto tiene sentido, pero en mi caso tengo esa consulta ejecutándose solo una vez y eso es después de la consulta de actualización. – TK123

+0

Tenga en cuenta que puede confirmar esto con 'SET SESSION query_cache_type = OFF;' antes de ejecutar cualquier otro comando. (Esto solo desactivará el caché de consultas para la conexión actual). –

Cuestiones relacionadas