sql >> Databasteknik >  >> RDS >> Sqlserver

Varför körs den andra T-SQL-frågan mycket snabbare än den första när den anropas av Reporting Services 2005 i en webbapp

Du kanske har stött på en fråga som har ett problem med parametersniffning, vilket har att göra med hur SQL Server försöker optimera din frågeexekveringsplan, men i de fall då Reporting Services är inblandad förstör det fullständigt och gör att det körs otroligt långsamt.

Jag hade ett fall med en rapport som hade två komplexa frågor på cirka 150 rader vardera men som kördes på 7 sekunder i min utvecklingsmiljö - hela rapporten tog mindre än 10 sekunder. Men när den distribuerades till produktions-SSRS-servern tog rapporten mer än 7 minuter och tog ofta timeout, vilket gjorde att rapporten inte kunde köras.

Den mesta informationen om det här problemet handlar om det i relation till lagrade procedurer. Avvisa inte detta eftersom du inte använder lagrade procedurer (som jag gjorde under en lång tid); det är mycket relevant för raka SQL-frågor också.

Så skillnaden du ser är att SQL Server skapar två mycket olika exekveringsplaner eftersom de två frågorna är strukturerade på olika sätt.

Lyckligtvis är lösningen väldigt enkel:lägg in parametrarna i interna variabler och använd dessa i din fråga istället. Jag gjorde detta med min rapport och produktionsrapporten gick tillbaka till 10 sekunder som utvecklingsversionen gjorde i Visual Studio.

För att kringgå parametersniffning för din första fråga skulle du få det att se ut så här:

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;



  1. Vad är SQL Server?

  2. Villkorligt SQL-antal

  3. ORA-27154 / ORA-27146

  4. Oracle SQL:Förstår du beteendet hos SYS_GUID() när det finns i en inline-vy?