2011-10-03 23 views
17

Tengo una consulta bastante simple que sigo obteniendo tiempos de espera (toma más de tres minutos para completar, lo detuve temprano para poder publicar esta pregunta) en cuando se ejecuta en código Sin embargo, cuando ejecuto la misma consulta desde la misma computadora en Sql Server Management Studio, la consulta solo tomará 2532 ms la primera consulta cuando los datos no estén en caché en el servidor y 524 ms para consultas repetidas.Consulta extremadamente lento en el código pero rápido en SSMS

Aquí está mi código C#

using (var conn = new SqlConnection("Data Source=backend.example.com;Connect Timeout=5;Initial Catalog=Logs;Persist Security Info=True;User ID=backendAPI;Password=Redacted")) 
       using (var ada = new SqlDataAdapter(String.Format(@" 
SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 {0}) {1} 
Order by dt desc" 
    , where.ToString(), (cbShowOnlyFailed.Checked ? "and Status = 1" : "")), conn)) 
{ 
    ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID); 
    ada.SelectCommand.Parameters.AddWithValue("@dt", dtpFilter.Value); 
    //ada.SelectCommand.CommandTimeout = 60; 
    conn.Open(); 
    Logs.Clear(); 
    ada.Fill(Logs); //Time out exception for 30 sec limit. 
} 

aquí es mi código estoy corriendo en SSMS, me la puso derecha desde ada.SelectCommand.CommandText

declare @clientID varchar(200) 
set @clientID = '138' 
declare @dt datetime 
set @dt = '9/19/2011 12:00:00 AM' 

SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 or job_type = 0 or job_type = 1 or job_type = 4) 
Order by dt desc 

qué está causando la discrepancia importante para la diferencia en el tiempo?


Para mantener limpia la sección de comentarios, responderé algunas preguntas frecuentes aquí.

La misma computadora y el inicio de sesión se utilizan tanto para la aplicación como para los sms.

En mi consulta de ejemplo solo se devuelven 15 filas. Sin embargo, es_history contiene 11351699 rows y es_history_dt contiene 8588493 rows. Ambas tablas están bien indexadas y el plan de ejecución en SSMS dice que están utilizando el índice busca las búsquedas, por lo que son búsquedas rápidas. El programa se comporta como si no estuviera utilizando los índices de la versión C# de la consulta.

+0

¿Usó el mismo usuario en SSMS que en el código? – bzlm

+1

¿Cuántas filas devuelve esta consulta? –

+0

@hugh, por favor, mira mi actualización ... –

Respuesta

31

Su código en SSMS no es el mismo código que ejecuta en su aplicación. Esta línea en su aplicación añade un parámetro NVARCHAR:

ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID); 

mientras que en el guión SSMS se declara como VARCHAR:

declare @clientID varchar(200) 

Debido a las reglas de Data Type Precedence la expresión Where client_id = @clientID en su consulta no es SARG -able donde @clientID es del tipo NVARCHAR (estoy dando un salto de fe y supongo que la columna client_id es de tipo VARCHAR). La aplicación obliga a una exploración de tabla donde la consulta SSMS puede hacer una búsqueda rápida de clave. Este es un problema bien conocido y entendido con el uso de Parameters.AddWithValue y se ha discutido en muchos artículos antes, por ejemplo. ver How Data Access Code Affects Database Performance. Una vez que el problema se entiende, las soluciones son triviales:

el abeto La solución st es superior porque resuelve el problema de contaminación de la memoria caché además del problema de la capacidad SARG.

También recomendaría que lea Slow in the Application, Fast in SSMS? Understanding Performance Mysteries

+0

En realidad, utilicé varchar porque la interfaz para la función pasó la ID del cliente como una cadena. Comprobé el esquema y Client_ID es realmente un int. Cambiarlo en mi código para convertir la cadena pasada a un int antes de ejecutar la consulta resolvió el problema. ¡Gracias! –

+0

También gracias por el último enlace, es muy útil. –

0

ejecutar el analizador en su conexión # c - puede haber otra actividad en curso que no son conscientes.

0

Capture el plan de ejecución desde ambos SSMS cuando ejecuta manualmente su consulta y luego desde Profiler cuando está ejecutando su aplicación. Comparar y contrastar.

0

Ejecute DBCC FREEPROCCACHE, como se sugiere here, solo para asegurarse de que el problema no se deba a un plan de ejecución de consulta obsoleto.

Cuestiones relacionadas