2010-05-13 46 views
5

Estamos tratando de optimizar algunas de nuestras consultas.¿Por qué usar una tabla temporal sería más rápido que una consulta anidada?

Una consulta está haciendo lo siguiente:

SELECT t.TaskID, t.Name as Task, '' as Tracker, t.ClientID, (<complex subquery>) Date, 
INTO [#Gadget] 
FROM task t 

SELECT TOP 500 TaskID, Task, Tracker, ClientID, dbo.GetClientDisplayName(ClientID) as Client 
FROM [#Gadget] 
order by CASE WHEN Date IS NULL THEN 1 ELSE 0 END , Date ASC 

DROP TABLE [#Gadget] 

(He quitado el complejo subconsulta no creo que sea relevante que no sea para explicar por qué esta consulta se ha realizado como un proceso de dos etapas.).

I pensaron que sería mucho más eficiente para combinar esto abajo en una sola consulta usando subconsultas como:

SELECT TOP 500 TaskID, Task, Tracker, ClientID, dbo.GetClientDisplayName(ClientID) 
FROM 
(
    SELECT t.TaskID, t.Name as Task, '' as Tracker, t.ClientID, (<complex subquery>) Date, 
    FROM task t 
) as sub  
order by CASE WHEN Date IS NULL THEN 1 ELSE 0 END , Date ASC 

Esto le daría al optimizador una mejor información para resolver lo que estaba pasando y evitar tablas temporales. Supuse que debería ser más rápido.

Pero resulta que es mucho más lento. 8 segundos frente a menos de 5 segundos.

No puedo entender por qué este sería el caso, ya que todo mi conocimiento de las bases de datos implica que las subconsultas siempre serán más rápidas que el uso de tablas temporales.

¿Qué me estoy perdiendo?

Editar -

Por lo que he podido ver en los planes de consulta, ambos son prácticamente idénticos, a excepción de la tabla temporal que tiene una operación extra "Insertar tabla" con un coste de 18 %

Obviamente, como tiene dos consultas, el costo de Sort Top N es mucho más alto en la segunda consulta que el costo del método Ordenar en la subconsulta, por lo que es difícil hacer una comparación directa de los costos.

Todo lo que puedo ver en los planes indica que el método de subconsulta sería más rápido.

+2

¿Ha comparado planes de consulta? – Oded

+0

@Oded, mira mi edición. –

+0

¿Borró la memoria caché de datos entre cada prueba? Si no, eso podría sesgar tu comparación – AdaTheDev

Respuesta

3

Obviamente, SQL Server elige un plan de consulta incorrecto. Sí, eso puede pasar, he tenido exactamente el mismo escenario que tú algunas veces.

El problema es que optimizar una consulta (mencionas una "subconsulta compleja") es una tarea no trivial: si tienes n tablas, ¡hay aproximadamente n! posibles pedidos de afiliados, y eso es solo el comienzo. Entonces, es bastante plausible que hacer (a) primero su consulta interna y (b) luego su consulta externa sea una buena manera de hacerlo, pero SQL Server no puede deducir esta información en un tiempo razonable.

Lo que puedes hacer es ayuda SQL Server. Como escribe Dan Tow en su excelente libro "SQL Tuning", la clave suele ser el orden de unión, yendo de la tabla más selectiva a la menos selectiva.Usando el sentido común (o el método descrito en su libro, que es mucho mejor), podría determinar qué orden de unión sería la más adecuada y luego usar la sugerencia de consulta FORCE ORDER.

De todos modos, cada consulta es única, no hay un "botón mágico" para hacer que SQL Server sea más rápido. Si realmente quiere saber qué está pasando, debe mirar (o mostrarnos) los planes de consulta de sus consultas. Otros datos interesantes se muestran en SET STATISTICS IO, que le indicará cuánto (costoso) acceso a HDD produce su consulta.

4

"debería ser" es algo peligroso de decir del rendimiento de la base de datos. A menudo he descubierto que las tablas temporales aceleran las cosas, a veces de forma espectacular. La explicación simple es que facilita al optimizador evitar la repetición del trabajo.

Por supuesto, también he visto tablas temporales hacer las cosas más lentas, a veces mucho más lento.

No hay sustituto para la creación de perfiles y el estudio de planes de consulta (sin embargo, lea sus estimaciones con un grano de sal).

0

he reiterado esta pregunta aquí: How can I force a subquery to perform as well as a #temp table?

El quid de la misma es, sí, entiendo que a veces es el optimizador derecho a entrometerse en sus subconsultas como si no fueran totalmente independientes, pero a veces hace un mal giro equivocado cuando trata de ser inteligente de una manera que todos conocemos. Estoy diciendo que debe haber una forma de desactivar esa "inteligencia" cuando sea necesario en lugar de arruinar un enfoque basado en la visualización con tablas temporales.

+0

Solo para actualizar. Martin Smith proporcionó una respuesta que funcionó para mí al señalar aquí: http://connect.microsoft.com/SQLServer/feedback/details/218968/ Es probable que haya solucionado el problema de este solicitante aunque Martin señaló que un spool no lo hace tienen estadísticas como las tablas temporales y es un truco que requiere una ORDEN BY que podría generar un costo real para algunos. – Adamantish

Cuestiones relacionadas