Pregunta

Reformé una sección lenta de una aplicación que heredamos de otra compañía para usar una unión interna en lugar de una subconsulta como

where id in (select id from ... )

La consulta refactorizada se ejecuta 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 todas indexadas. ¿SQL ejecuta la consulta en la cláusula where una vez por fila o algo así?

Actualizar : explique los resultados:

La diferencia está en la segunda parte de la " donde id en () " consulta -

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
¿Fue útil?

Solución

Una "subconsulta correlacionada" (es decir, una en la que la condición where depende de los valores obtenidos de las filas de la consulta contenedora) se ejecutará una vez para cada fila. Una subconsulta no correlacionada (una en la que la condición donde es independiente de la consulta contenedora) se ejecutará una vez al principio. El motor SQL hace esta distinción automáticamente.

Pero, sí, la explicación-plan le dará los detalles sucios.

Otros consejos

Está ejecutando la subconsulta una vez por cada fila mientras que la unión se realiza en los índices.

Este es un ejemplo de cómo subconsultas se evalúan en MySQL 6.0 .

El nuevo optimizador convertirá este tipo de subconsultas en uniones.

Ejecuta el plan de explicación en cada versión, te dirá por qué.

antes de que se ejecuten las consultas en el conjunto de datos a través de un optimizador de consultas, el optimizador intenta organizar la consulta de tal manera que pueda eliminar tantas tuplas (filas) del conjunto de resultados tan rápido como sea posible. A menudo, cuando se utilizan subconsultas (especialmente las malas), las tuplas no se pueden eliminar 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 sería algo que el optimizador no podría hacer mucho mejor. Ejecutar "explicar" le mostrará el método de optimización para recuperar los datos.

Por lo general, es el resultado de que el optimizador no pueda darse cuenta de que la subconsulta se puede ejecutar 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 en la que están haciendo consultas. Algunos de los más " enterprisey " Las bases de datos son mejores en esto, pero a veces lo extrañan.

Esta pregunta es algo general, así que aquí hay una respuesta general:

Básicamente, las consultas tardan más tiempo cuando MySQL tiene toneladas de filas para clasificar.

Haz esto:

Ejecute un EXPLICACIÓN en cada una de las consultas (la CONJUNTA, luego la Subsistida) 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.

La subconsulta donde debe ejecutar 1 consulta para cada fila devuelta. La unión interna solo tiene que ejecutar una consulta.

Mire el plan de consulta para cada consulta.

Where in y Join pueden normalmente implementarse usando el mismo plan de ejecución, por lo que normalmente hay cero acelera de cambiar entre ellos.

El optimizador no hizo un muy buen trabajo. Por lo general, pueden transformarse sin ninguna diferencia y el optimizador puede hacer esto.

La subconsulta probablemente estaba ejecutando un " exploración de tabla completa " ;. En otras palabras, no usar el índice y devolver demasiadas filas que el Where desde la consulta principal necesitaba filtrar.

Solo una suposición sin detalles, por supuesto, pero esa es la situación común.

Con una subconsulta, tiene que volver a ejecutar el segundo SELECT para cada resultado, y cada ejecución generalmente devuelve 1 fila.

Con una unión, el 2nd SELECT devuelve muchas más filas, pero solo tienes que ejecutarlo una vez. La ventaja es que ahora puede unirse a los resultados, y unir las relaciones es lo que se supone que una base de datos es buena. Por ejemplo, tal vez el optimizador pueda detectar cómo aprovechar mejor un índice ahora.

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.

Tomado del Manual de referencia ( 14.2.10.11 Reescritura de subconsultas como Se une ):

  

UN IZQUIERDO [EXTERNO] UNE puede ser más rápido que una subconsulta equivalente porque el servidor podría optimizarlo mejor & # 8212; un hecho que no es específico del Servidor MySQL solo.

Por lo tanto, las subconsultas pueden ser más lentas de lo que la IZQUIERDA [EXTERNA] SE UNE.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top