Subconsultas vs uniones


Refactoricé una sección lenta de una aplicación que heredamos de otra empresa 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 ¿puede alguien 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 - Explicar los resultados:

El 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

14 answers

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 where es independiente de la consulta contenedora) se ejecutará una vez al principio. El motor SQL hace esta distinción automáticamente.

Pero, sí, explícate-plan te dará los detalles sucios.

 151
Author: Jeffrey L Whitledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:03:42

Está ejecutando la subconsulta una vez por cada fila mientras que la combinación ocurre en los índices.

 36
Author: Sklivvz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:01:12

He aquí un ejemplo de cómo se evalúan las subconsultas en MySQL 6.0.

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

 16
Author: Giuseppe Maxia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 07:19:08

Ejecute el plan explain en cada versión, le dirá por qué.

 7
Author: scotta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:00:10

Antes de que las consultas se ejecuten contra el conjunto de datos que se ponen 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 pueda. A menudo, cuando utiliza 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 lo que era tan malo sobre el original, pero mi conjetura sería que era algo que el optimizador no podía hacer mucho mejor. Ejecutar 'explain' le mostrará el método de optimizadores para recuperar los datos.

 6
Author: pfranza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:06:24

Generalmente es el resultado de que el optimizador no puede averiguar 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 que está consultando. Algunas de las bases de datos más "emprendedoras" son mejores en esto, pero todavía lo echan de menos a veces.

 4
Author: Mark Roddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:03:02

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

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

Haz esto:

Ejecute una EXPLICACIÓN en cada una de las consultas (la JOIN'ed, luego la Subqueried), 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.

 4
Author: Pete Karl II,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:05:45

La subconsulta where tiene que ejecutar 1 consulta por cada fila devuelta. La unión interna solo tiene que ejecutar 1 consulta.

 4
Author: Shawn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:18:32

Mire el plan de consulta para cada consulta.

Donde en y Join puede típicamente implementarse usando el mismo plan de ejecución, por lo que típicamente no hay ninguna velocidad de cambio entre ellos.

 3
Author: Amy B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:01:05

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

 3
Author: Cade Roux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:01:34

La subconsulta probablemente estaba ejecutando un "análisis completo de tabla". 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.

 3
Author: igelkott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:02:58

Con una subconsulta, debe volver a ejecutar la 2a SELECCIÓN para cada resultado, y cada ejecución normalmente devuelve 1 fila.

Con una combinación, la 2a 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, tal vez el optimizador pueda detectar cómo aprovechar mejor un índice ahora.

 2
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:02:04

No es tanto la subconsulta como la cláusula IN, aunque las uniones están en la base de al menos el motor SQL de Oracle y se ejecutan extremadamente rápido.

 2
Author: dacracot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 19:02:52

Tomado del Manual de Referencia ( 14.2.10.11 Reescribir Subconsultas como Joins):

Una UNIÓN [EXTERNA] IZQUIERDA puede ser más rápida que una subconsulta equivalente porque el servidor podría ser capaz de optimizarla mejor, un hecho que no es específico solo del servidor MySQL.

Así que las subconsultas pueden ser más lentas que las UNIONES [EXTERNAS] IZQUIERDAS.

 2
Author: simhumileco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-26 06:05:27