2009-08-07 18 views
5

Estoy intentando comprender mejor por qué esta optimización de consultas es tan significativa (más de 100 veces más rápida), así que puedo reutilizar una lógica similar para otras consultas.por qué MySQL JOIN es significativamente más rápido que WHERE IN (subconsulta)

Uso de MySQL 4.1 - RESET QUERY CACHE y FLUSH TABLES se realizaron antes de que todas las consultas y el tiempo de resultado se puedan reproducir de forma consistente. Lo único que es obvio para mí en el EXPLAIN es que solo se deben encontrar 5 filas durante el JOIN? ¿Pero esa es la respuesta completa a la velocidad? Ambas consultas están utilizando un índice parcial (forum_stickies) para determinar el estado de los temas Suprimido (topic_status = 0)

Imágenes para el análisis más profundo con EXPLAIN

consulta lenta: 0.7+ segundo (caché despejado)

SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics 
WHERE topic_last_post_id IN 
(SELECT SQL_NO_CACHE MAX (topic_last_post_id) AS topic_last_post_id 
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id) 

consulta rápida: 0.004 segundos o menos (caché borra)

SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics AS s1 
JOIN 
(SELECT SQL_NO_CACHE MAX(topic_last_post_id) AS topic_last_post_id 
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id) AS s2 
ON s1.topic_last_post_id=s2.topic_last_post_id 

cuenta que no hay índice en la columna más importante (topic_last_post_id), pero que no se puede evitar (los resultados se almacenan para su uso repetido de todos modos).

¿Es la respuesta simplemente porque la primera consulta tiene que escanear topic_last_post_id DOS VECES, la segunda vez para hacer coincidir los resultados con la subconsulta? Si es así, ¿por qué es exponencialmente más lento?

(menos importantes Tengo curiosidad por qué la primera consulta todavía lleva tanto tiempo si realmente no poner un índice en topic_last_post_id)

actualización: He encontrado este hilo en stackoverflow después de mucho buscar posterior en que entra en este tema Subqueries vs joins

Respuesta

4

Quizás el motor ejecuta la subconsulta para cada fila en bb_topics, solo para ver si encuentra el topic_last_post_id en los resultados. Sería estúpido, pero también explicaría la gran diferencia.

+1

Wow eso podría ser posible. Solo había considerado que tal vez hace la consulta para cada uno de los id en los resultados del grupo (5 de ellos) pero ahora que lo mencionas, me pregunto si lo hace para las 209 (o incluso para las 293) filas. Envié una solicitud a alguien para intentar las consultas en un conjunto de datos mucho más grande (10.000 filas frente a 300) para ver si el problema se magnifica aún más, lo que probaría la teoría. –

+1

Me acaba de ocurrir que también intente esto simplemente consulta 'SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics WHERE topic_last_post_id IN (1516,1567,1572,1569,1578)' y es extremadamente rápido. Así que tienes razón, está ejecutando la subconsulta para cada fila, ¡vaya! Eso es una locura. –

+0

Esto parece estar solucionado en 5.6 (ya no es una "SUBCONTRIA DEPENDIENTE"), y el rendimiento es similar a un JOIN. – Vatev

0

Yo diría que dado que el argumento dentro de la cláusula IN() puede ser lo que sea que se pegue allí, el DB tiene que verificar todo lo que se devuelve. Cuando se une a las tablas, hay muchas tácticas de mejora del rendimiento que se emplean, por ejemplo, probablemente utiliza índices para su ventaja.

Cuestiones relacionadas