¿Por qué la segunda consulta de T-SQL se ejecuta mucho más rápido que la primera cuando Reporting Services 2005 lo llamó en una aplicación web?

Con la adición de parens en la subconsulta, los resultados se devolvieron inmediatamente en la aplicación.

Esto funciona lento cuando es llamado por RS2005 en una aplicación web vb.net / aspx:

SELECT c.TeacherID, u.FName + ' ' + u.lname as Teacher, count(sb.behaviorID) as BxCount, sb.behaviorID, b.BehaviorName, std.GradeID, gl.GradeLevel FROM StudentBehaviors sb join Classes c on sb.classid = c.classid join StudentDetails std on sb.studentID = std.StudentID and std.RecordIsActive=1 join users u on c.TeacherID = u.UserID join Behaviors b on sb.behaviorID = b.BehaviorID join GradeLevels gl on std.GradeID = gl.GradeLevelID WHERE sb.classdate between @StartDate and @EndDate and c.schoolid = @SchoolID and std.GradeID=@GradeLevel GROUP BY c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName, std.GradeID, gl.GradeLevel ORDER BY u.LName, sb.behaviorID 

Esto corre rápido:

 select a.teacherid, a.teacher,a.bxcount, a.behaviorid,a.behaviorname,a.gradeid, a.gradelevel from ( SELECT c.TeacherID, u.FName + ' ' + u.lname as Teacher, count(sb.behaviorID) as BxCount, sb.behaviorID, b.BehaviorName, std.GradeID, gl.GradeLevel FROM StudentBehaviors sb join Classes c on sb.classid = c.classid join StudentDetails std on sb.studentID = std.StudentID and std.RecordIsActive=1 join users u on c.TeacherID = u.UserID join Behaviors b on sb.behaviorID = b.BehaviorID join GradeLevels gl on std.GradeID = gl.GradeLevelID WHERE sb.classdate between @StartDate and @EndDate and c.schoolid = @SchoolID and std.GradeID=@GradeLevel group by c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName, std.GradeID, gl.GradeLevel ) a order by a.teacher, a.behaviorid 

Se ejecutan a la misma velocidad en una ventana de consulta en SQL Server Management Studio. ¿Por qué la diferencia? Gracias.

Es posible que hayas encontrado una consulta que tiene un problema con el rastreo de parámetros , que tiene que ver con cómo Sql Server trata de optimizar tu plan de ejecución de consultas, pero en los casos en que Reporting Services está involucrado, lo arruina completamente y lo hace funcionar increíblemente lento.

Tuve un caso con un informe que tenía dos consultas complejas de alrededor de 150 líneas cada una, pero que se ejecutó en 7 segundos en mi entorno de desarrollo: el informe completo tardó menos de 10 segundos. Sin embargo, cuando se implementó en el servidor SSRS de producción, el informe tardó más de 7 minutos y, a menudo, se agotó el tiempo de espera para que el informe no se pueda ejecutar.

La mayoría de la información sobre este tema habla sobre esto en relación con los procedimientos almacenados. No descarte esto porque no está usando procedimientos almacenados (como lo hice hace mucho tiempo); es muy relevante para las consultas Sql directas también.

Entonces, la diferencia que está viendo es que SQL Server está creando dos planes de ejecución muy diferentes ya que las dos consultas están estructuradas de manera diferente.

Afortunadamente, la solución es muy simple: ponga los parámetros en variables internas y utilícelos en su consulta en su lugar. Hice esto con mi informe y el informe de producción volvió a 10 segundos, como la versión de desarrollo en Visual Studio.

Para omitir la detección de parámetros para su primera consulta, debería hacer que se vea así:

 BEGIN -- Use internal variables to solve parameter sniffing issues DECLARE @StartDateInternal AS DATETIME; DECLARE @EndDateInternal AS DATETIME; DECLARE @SchoolIDInternal AS INT; DECLARE @GradeLevelInternal AS INT; -- Copy the parameters into the internal variables SET @StartDateInternal = @StartDate; SET @EndDateInternal = @EndDate; SET @SchoolIDInternal = @SchoolID; SET @GradeLevelInternal = @GradeLevel; -- Now use the internal variables in your query rather than the parameters SELECT c.TeacherID, u.FName + ' ' + u.lname as Teacher, count(sb.behaviorID) as BxCount, sb.behaviorID, b.BehaviorName, std.GradeID, gl.GradeLevel FROM StudentBehaviors sb join Classes c on sb.classid = c.classid join StudentDetails std on sb.studentID = std.StudentID and std.RecordIsActive=1 join users u on c.TeacherID = u.UserID join Behaviors b on sb.behaviorID = b.BehaviorID join GradeLevels gl on std.GradeID = gl.GradeLevelID WHERE sb.classdate between @StartDateInternal and @EndDateInternal and c.schoolid = @SchoolIDInternal and std.GradeID = @GradeLevelInternal GROUP BY c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName, std.GradeID, gl.GradeLevel ORDER BY u.LName, sb.behaviorID; END;