2011-09-08 15 views
5

he descubierto que en algunos casos una consulta comoservidor SQL unirse vs pregunta de desempeño subconsulta

select 
    usertable.userid, 
    (select top 1 name from nametable where userid = usertable.userid) as name 
from usertable 
where active = 1 

lleva un orden de magnitud más tiempo en completarse en SS2008R2 que el equivalente consulta de combinación

select 
    usertable.userid, 
    nametable.name 
from usertable 
left join nametable on nametable.userid = usertable.userid 
where usertable.active = 1 

donde ambos las tablas están indexadas y tienen más de 100k filas. Curiosamente, la inserción de una cláusula de la parte superior en la consulta original hace realizar a la par con la consulta de unión:

select 
    top (select count(*) from usertable where active = 1) usertable.userid, 
    (select top 1 name from nametable where userid = usertable.userid) as name 
from usertable 
where active = 1 

¿Alguien tiene alguna idea de por qué la consulta original lleva a cabo tan mal?

+3

FYI al diagnosticar problemas de rendimiento que siempre debe tener un plan de ejecución de la consulta. – Justin

+0

Si tiene acceso a Safari Books Online, consulte "Inside Microsoft® SQL Server 2005: Afinación y optimización de consultas - capítulo 3" u Otro buen enlace http://blogs.msdn.com/b/craigfr/archive/2006 /09/27/774107.aspx –

Respuesta

3

Bueno, las consultas son diferentes: a menos que la columna userid sea una clave principal o tenga una restricción de exclusividad, la segunda consulta podría devolver más filas que la primera.

Dicho esto, con la suposición de que id de usuario es una clave principal/oportunidad única eliminación de la parte TOP 1 de la primera sub consulta:

select 
    usertable.userid, 
    (select name from nametable where userid = usertable.userid) as name 
from usertable 
where active = 1 
+0

Eso fue lo que hizo el truco. Lo tenía allí como precaución para evitar errores de tiempo de ejecución ya que la consulta se genera sobre la marcha. Ahora necesito averiguar si puedo eliminarlo de forma segura como regla general. –

2

Es una subconsulta correlacionada, lo que significa que debe ejecutarse una vez por cada fila de retorno de la consulta externa ya que hace referencia a un campo en la consulta externa.

A JOIN se ejecuta una vez para todo el conjunto de resultados y se fusiona. Su subconsulta ejecuta la consulta externa, luego para cada fila devuelta ejecuta la subconsulta de nuevo.

+1

No creo que esto sea cierto con SQL Server. – JeffO

+2

@Jeff - entonces estás equivocado. – JNK

1

La consulta original ejecutará el sub select tantas veces como filas haya, por lo tanto, el bajo rendimiento.

Cuando obtiene JOIN obtiene el conjunto completo de resultados a la vez.