为什么第二个T-SQL查询比第一个在Web应用程序中由Reporting Services 2005调用时运行得快得多

use*_*692 3 t-sql sql-server asp.net performance reporting-services

通过在子查询中添加parens,结果立即在应用程序中返回.

当RS2005在vb.net/aspx web应用程序中调用时,运行速度很慢:

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
Run Code Online (Sandbox Code Playgroud)

这快速运行:

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
Run Code Online (Sandbox Code Playgroud)

它们在SQL Server Management Studio的查询窗口中以相同的速度运行.为什么不同?谢谢.

Chr*_*tta 5

您可能遇到过一个参数嗅探问题的查询,这与Sql Server如何尝试优化您的查询执行计划有关,但是在涉及Reporting Services时会完全混淆并使其运行速度极慢.

我有一个案例的报告有两个复杂的查询,每个约150行,但在我的开发环境中运行7秒 - 整个报告花了不到10秒.但是,当部署到生产SSRS服务器时,报告花了超过7分钟,并且经常超时,使报告无法运行.

有关此问题的大多数信息都与存储过程有关.不要忽视这一点,因为你没有使用存储过程(就像我做了很长时间); 它也与直接的Sql查询非常相关.

因此,您看到的差异是Sql Server正在创建两个非常不同的执行计划,因为两个查询的结构不同.

幸运的是,解决方案非常简单:将参数放入内部变量并在查询中使用它们.我用我的报告做了这个,生产报告回到了10秒,就像Visual Studio中的开发版本一样.

要绕过第一个查询的参数嗅探,您可能会看起来像这样:

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;
Run Code Online (Sandbox Code Playgroud)