2010-08-25 12 views
5

Estoy desarrollando un sistema que periódicamente (4-5 veces al día) ejecuta una instrucción select, que normalmente toma menos de 10 segundos, pero que periódicamente toma hasta 40 minutos.Pregunta lenta intermitente en SQL Server 2008

La base de datos está en Windows Server 2008 + SQL Server 2008 R2; ambos 64 bits.

Hay un servicio en la máquina que ejecuta la base de datos que sondea la base de datos y genera valores para los registros que lo requieren. Estos registros se consultan periódicamente utilizando una selección de combinación de varias tablas de un servicio en una segunda máquina escrita en C++ (VS 2010) utilizando la clase CRecordset de MFC para extraer los datos. A continuación, se muestra un ejemplo de la consulta que causa el problema.

SELECT DISTINCT "JobKeysFrom"."Key" AS "KeyFrom","KeysFrom"."ID" AS "IDFrom", 
"KeysFrom"."X" AS "XFrom","KeysFrom"."Y" AS "YFrom","JobKeysTo"."Key" AS "KeyTo", 
"KeysTo"."ID" AS "IDTo","KeysTo"."X" AS "XTo","KeysTo"."Y" AS "YTo", 
"Matrix"."TimeInSeconds","Matrix"."DistanceInMetres","Matrix"."Calculated" 
FROM "JobKeys" AS "JobKeysFrom" 
INNER JOIN "JobKeys" AS "JobKeysTo" ON 
("JobKeysFrom"."Key"<>"JobKeysTo"."Key") AND 
("JobKeysFrom"."JobID"=531) AND 
("JobKeysTo"."JobID"=531) 
INNER JOIN "Keys" AS "KeysFrom" ON 
("JobKeysFrom"."Key"="KeysFrom"."Key") AND ("JobKeysFrom"."Status"=4) 
INNER JOIN "Keys" AS "KeysTo" ON 
("JobKeysTo"."Key"="KeysTo"."Key") AND ("JobKeysTo"."Status"=4) 
INNER JOIN "Matrix" AS "Matrix" ON 
("Matrix"."IDFrom"="KeysFrom"."ID") AND ("Matrix"."IDTo"="KeysTo"."ID") 
ORDER BY "JobKeysFrom"."Key","JobKeysTo"."Key" 

He intentado el siguiente

  1. comprobado los índices y todos parecen correctos y que están activos y están siendo utilizados de acuerdo con la consulta
  2. el asesor de diseño regresa con ninguna sugerencia
  3. He intentado desfragmentar los índices y los datos
  4. he reconstruido la base de datos desde cero exportando los datos y volviéndolos a importar en una nueva base de datos.
  5. ejecutó el generador de perfiles y encontró que cuando sale mal parece que hace muchos millones (hasta 100 millones) de lecturas en lugar de unos pocos cientos de miles.
  6. corrieron la base de datos en un servidor diferente

Durante el tiempo que se está ejecutando la consulta, puedo correr exactamente la misma consulta en la ventana del estudio de gestión y será volver a correr en 10 segundos. El problema no parece estar relacionado con el bloqueo, el interbloqueo, la CPU, el disco o la memoria, tal como lo ha hecho cuando el equipo que ejecutaba la base de datos solo ejecutaba esta única consulta. El servidor tiene 4 procesadores y 16 gb de memoria para ejecutarlo. También intenté actualizar los discos a otros mucho más rápidos y esto no tuvo ningún efecto.

Me parece que es casi como si la base de datos recibe la consulta, comienza a procesarla y luego se va a dormir durante 40 minutos o ejecuta la consulta sin usar los índices.

Cuando pasa mucho tiempo, con el tiempo terminará y enviará los resultados de la consulta (normalmente unos 70-100000 registros) de vuelta a la aplicación de llamada.

Cualquier ayuda o sugerencia será recibida con gratitud, muchas gracias

+0

¿Se ejecuta esta consulta como un procedimiento almacenado parametrizado? –

+0

¿Se puede evitar SELECT DISTINCT? Esto puede dañar el rendimiento de forma vertiginosa. –

+1

@Yves: parece que es lo suficientemente eficiente como para ejecutar Adhoc y vuelve en 10 segundos. –

Respuesta

3

Esto se parece mucho a la inhalación de parámetro.

Cuando se invoca un procedimiento almacenado y no existe un plan de ejecución en la memoria caché que coincida con las opciones set para la conexión, se compilará un nuevo plan de ejecución utilizando los valores de parámetros pasados ​​en esa invocación.

A veces, esto sucederá cuando los parámetros pasados ​​son atípicos (por ejemplo, tienen una selectividad inusualmente alta) por lo que el plan generado no será adecuado para la mayoría de las otras invocaciones con diferentes parámetros. Por ejemplo, puede elegir un plan con búsqueda de índices y búsquedas de marcadores, lo cual es bueno para un caso altamente selectivo, pero deficiente si debe hacerse cientos de miles de veces.

Esto explicaría por qué el número de lecturas llega hasta el techo.

Su conexión SSMS probablemente tendrán diferentes SET ... opciones para que no quede entregado el mismo plan problemática de la caché cuando se ejecuta el procedimiento almacenado dentro de SSMS

Se puede utilizar el siguiente para obtener el plan de la lenta sesión

select p.query_plan, * 
from sys.dm_exec_requests r 
cross apply sys.dm_exec_query_plan(r.plan_handle) p 
where r.session_id = <session_id> 

Luego, compare con el plan para la buena sesión.

Si determina que el olfateo de los parámetros tiene la culpa, puede utilizar las sugerencias OPTIMIZE FOR para evitar que elija el plan incorrecto.

+0

Creo que construimos nuestros discursos sobre las condiciones y declaraciones iniciales no válidas :) – garik

0

Compruebe que no tiene una tarea de mantenimiento ejecutándose que está reconstruyendo índices, o que las estadísticas de su base de datos de alguna manera son inválidas cuando se ejecuta la consulta.

Esto es exactamente el tipo de cosa que uno esperaría ver si la consulta no usa sus índices, que generalmente es porque los índices no son accesibles para la consulta en el punto donde se ejecuta o porque las estadísticas no son válidas y haga que el optimizador crea que sus tablas grandes solo tienen algunas filas y la consulta se ejecutará más rápido con una exploración de tabla completa que utilizando acceso indexado.

+0

¿No entendió que una ejecución concurrente de la misma consulta regresa rápidamente? –