Refactoré una sección lenta de una aplicación que heredamos de otra compañía para usar una combinación interna en lugar de una subconsulta como:
WHERE id IN (SELECT id FROM ...)
La consulta refactorizada se ejecuta aproximadamente 100 veces más rápido. (~ 50 segundos a ~ 0.3) Esperaba una mejora, pero ¿alguien puede explicar por qué fue tan drástico? Las columnas utilizadas en la cláusula where fueron indexadas. ¿SQL ejecuta la consulta en la cláusula where una vez por fila o algo así?
Actualización - Explicar los resultados:
La diferencia está en la segunda parte de la consulta "where id in ()":
2 DEPENDENT SUBQUERY submission_tags ref st_tag_id st_tag_id 4 const 2966 Using where
vs 1 fila indexada con la unión:
SIMPLE s eq_ref PRIMARY PRIMARY 4 newsladder_production.st.submission_id 1 Using index
sql
mysql
performance
database-design
join
palmsey
fuente
fuente
Respuestas:
Una "subconsulta correlacionada" (es decir, una en la que la condición where depende de los valores obtenidos de las filas de la consulta que contiene) se ejecutará una vez para cada fila. Una subconsulta no correlacionada (una en la que la condición where es independiente de la consulta que lo contiene) se ejecutará una vez al principio. El motor SQL hace esta distinción automáticamente.
Pero sí, explicar-plan te dará los detalles sucios.
fuente
DEPENDENT SUBQUERY
significa exactamente lo mismo que "subconsulta correlacionada".Está ejecutando la subconsulta una vez por cada fila, mientras que la unión ocurre en los índices.
fuente
EXPLAIN
diceDEPENDENT SUBQUERY
, que es el indicador más claro de este comportamiento.Aquí hay un ejemplo de cómo se evalúan las subconsultas en MySQL 6.0 .
El nuevo optimizador convertirá este tipo de subconsultas en combinaciones.
fuente
Ejecute el plan de explicación en cada versión, le dirá por qué.
fuente
antes de que las consultas se ejecuten en el conjunto de datos, se someten a un optimizador de consultas, el optimizador intenta organizar la consulta de tal manera que pueda eliminar tantas tuplas (filas) del conjunto de resultados lo más rápido posible. A menudo, cuando utiliza subconsultas (especialmente las malas), las tuplas no pueden eliminarse del conjunto de resultados hasta que la consulta externa comience a ejecutarse.
Sin ver la consulta, es difícil decir qué tenía de malo el original, pero supongo que fue algo que el optimizador no pudo mejorar mucho. Ejecutar 'explicar' le mostrará el método de optimizadores para recuperar los datos.
fuente
Mire el plan de consulta para cada consulta.
¿En qué lugar y Únete puede normalmente ser implementado usando el mismo plan de ejecución, por lo que normalmente no es cero aceleración de cambiar entre ellos.
fuente
Optimizer no hizo un muy buen trabajo. Por lo general, se pueden transformar sin ninguna diferencia y el optimizador puede hacer esto.
fuente
Por lo general, es el resultado de que el optimizador no puede darse cuenta de que la subconsulta puede ejecutarse como una combinación, en cuyo caso ejecuta la subconsulta para cada registro en la tabla en lugar de unir la tabla en la subconsulta contra la tabla que está consultando. Algunas de las bases de datos más "empresariales" son mejores en esto, pero a veces aún lo echan de menos.
fuente
Esta pregunta es algo general, así que aquí hay una respuesta general:
Básicamente, las consultas tardan más cuando MySQL tiene toneladas de filas para ordenar.
Hacer esto:
Ejecute un EXPLICAR en cada una de las consultas (la UNIDA, luego la Subconsulta), y publique los resultados aquí.
Creo que ver la diferencia en la interpretación de MySQL de esas consultas sería una experiencia de aprendizaje para todos.
fuente
La subconsulta where tiene que ejecutar 1 consulta por cada fila devuelta. La unión interna solo tiene que ejecutar 1 consulta.
fuente
La subconsulta probablemente estaba ejecutando una "exploración de tabla completa". En otras palabras, no usar el índice y devolver demasiadas filas que el Where de la consulta principal necesitaba filtrar.
Solo una suposición sin detalles, por supuesto, pero esa es la situación común.
fuente
Con una subconsulta, debe volver a ejecutar el segundo SELECCIONAR para cada resultado, y cada ejecución generalmente devuelve 1 fila.
Con una unión, la 2da SELECCIÓN devuelve muchas más filas, pero solo tiene que ejecutarla una vez. La ventaja es que ahora puede unirse a los resultados, y unir relaciones es en lo que se supone que una base de datos es buena. Por ejemplo, quizás el optimizador pueda detectar cómo aprovechar mejor un índice ahora.
fuente
No es tanto la subconsulta como la cláusula IN, aunque las uniones son la base de al menos el motor SQL de Oracle y se ejecutan extremadamente rápido.
fuente
Tomado del Manual de referencia ( 14.2.10.11 Reescritura de subconsultas como uniones ):
Por lo tanto, las subconsultas pueden ser más lentas que las de IZQUIERDA [EXTERIOR].
fuente