2011-01-25 4 views
26

Estoy trabajando en la reescritura de algunas consultas SQL mal escritas y están sobreutilizando subconsultas. Estoy buscando las mejores prácticas con respecto al uso de subconsultas.Cuándo utilizar subconsultas de SQL en comparación con una combinación estándar?

Cualquier ayuda sería apreciada.

+0

No es que no haya una solución mágica: el problema es que la pregunta es demasiado amplia para que se pueda responder de manera razonable.No hay garantía de que lo que funciona en una base de datos (MySQL) funcione exactamente igual en otro. La regla más simple es que si la (s) columna (s) de la subconsulta están en el conjunto de resultados final, use un JOIN - es el medio más óptimo para obtener datos de dos tablas. De lo contrario, una subconsulta está bien, pero las correlacionadas pueden causar problemas (aunque no con EXISTS). –

+1

¿En base a qué afirma que se están utilizando en exceso las consultas secundarias? Parece extraño decidir que _y luego_ pedir información sobre las mejores prácticas para usar subconsultas. –

+1

Posible duplicado de [Unir frente a una subconsulta] (http://stackoverflow.com/questions/2577174/join-vs-sub-query) –

Respuesta

39

Las subconsultas suelen estar bien a menos que sean subconsultas dependientes (también conocido como correlated subqueries). Si solo está utilizando subconsultas independientes y están utilizando índices apropiados, entonces deberían ejecutarse rápidamente. Si tiene una subconsulta dependiente, puede encontrarse con problemas de rendimiento porque una subconsulta dependiente normalmente se debe ejecutar una vez para cada fila en la consulta externa. Entonces, si su consulta externa tiene 1000 filas, la subconsulta se ejecutará 1000 veces. Por otro lado, una subconsulta independiente normalmente solo debe evaluarse una vez.

Si no está seguro de lo que significa que una subconsulta sea dependiente o independiente aquí hay una regla general: si puede tomar la subconsulta, eliminarla de su contexto, ejecutarla y obtener un conjunto de resultados, entonces es una independent subquery.

Si obtiene un error de sintaxis porque se refiere a algunas tablas fuera de la subconsulta, entonces es un dependent subquery.

La regla general, por supuesto, tiene algunas excepciones. Por ejemplo:

  • Muchos optimizadores pueden tomar una subconsulta dependiente y encontrar una forma de ejecutarla eficientemente como un JOIN. Por ejemplo, una consulta NOT EXISTS puede dar como resultado un plan de consulta ANTI JOIN, por lo que no necesariamente será más lento que escribir la consulta con un JOIN.
  • MySQL tiene un bug donde una subconsulta independiente dentro de una expresión IN se identifica incorrectamente como una subconsulta dependiente y, por lo tanto, se utiliza un plan de consulta subóptimo. Esto aparentemente está arreglado en las versiones más nuevas de MySQL.

Si el rendimiento es un problema, mida sus consultas específicas y vea qué funciona mejor para usted.

+0

Por correlacionado, ¿quiere decir que contiene una referencia a una columna en la consulta externa? –

+0

@El Ronnoco: Sí –

+3

"Muchos optimizadores pueden tomar una subconsulta dependiente y encontrar una manera de ejecutarla de manera eficiente" - Estoy de acuerdo con esta afirmación y niega todo su argumento, es decir, "Las subconsultas correlacionadas son malas excepto cuando no son malas" . – onedaywhen

4

Lamentablemente, la respuesta depende en gran medida del servidor SQL que esté utilizando. En teoría, las uniones son mejores desde el punto de vista de la teoría pura relacional. Permiten que el servidor haga lo correcto bajo el capó y les da más control y, por lo tanto, al final puede ser más rápido. Si el servidor está bien implementado. En la práctica, algunos servidores SQL funcionan mejor si lo engañas para optimizar sus consultas a través de subconsultas y similares.

+0

Algunas subconsultas también pueden promocionarse para unirse (dependiendo del servidor, de curso). Para la mayoría de los casos, encuentro que las uniones "se ajustan mejor a mi cabeza". –

+0

No, si un servidor está bien implementado, reconocerá la forma más rápida de realizar una ENTRADA o una subconsulta y producir el plan de ejecución óptimo. Si el JOIN y la subconsulta son algebraicamente iguales, entonces un servidor bien implementado producirá el mismo plan de ejecución. –

+0

Sí ... Todo es cierto. Si un servidor se implementa perfectamente, siempre optimizará sus consultas rotas también ;-) Pero ... ese fue mi punto principal: casi todos los servidores sql funcionan mejor si construye sus consultas de acuerdo con su comportamiento. Es una desafortunada verdad. Por lo general, cuanto más tiempo haya existido un producto, más probabilidades hay de que haga un mejor trabajo sin importar cómo organice sus consultas. Pero incluso eso no siempre es verdad. –

5

No hay ninguna bala de plata aquí. Todos y cada uno de los usos deben evaluarse de forma independiente. Hay algunos casos en los que subconsultas correlacionadas son claras ineficaz, éste está mejor escrito a continuación como un JOIN

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc) 
from users u 

Por otro lado, existe y existe no ganarán consultas a lo largo de uniones.

select ... 
where NOT EXISTS (.....) 

normalmente es más rápido que

select ... 
FROM A LEFT JOIN B 
where B.ID is null 

Sin embargo, incluso estas generalizaciones pueden ser falsas para cualquier esquema particular y distribución de datos.

+3

... y RDBMS :-) –

Cuestiones relacionadas