Du er muligvis stødt på en forespørgsel, der har et problem med parametersniffing, hvilket har at gøre med, hvordan SQL Server forsøger at optimere din plan for udførelse af forespørgsler, men i tilfælde, hvor Reporting Services er involveret, roder det fuldstændig sammen og får det til at køre utroligt langsomt.
Jeg havde en sag med en rapport, der havde to komplekse forespørgsler på omkring 150 linjer hver, men som kørte på 7 sekunder i mit udviklingsmiljø - hele rapporten tog mindre end 10 sekunder. Men når rapporten blev implementeret på produktions-SSRS-serveren, tog den mere end 7 minutter og fik ofte timeout, hvilket gjorde rapporten ubrugelig.
De fleste oplysninger om dette problem taler om det i forhold til lagrede procedurer. Afvis ikke dette, fordi du ikke bruger lagrede procedurer (som jeg gjorde i lang tid); det er også meget relevant for straight Sql-forespørgsler.
Så forskellen, du ser, er, at SQL Server opretter to meget forskellige eksekveringsplaner, da de to forespørgsler er struktureret forskelligt.
Heldigvis er løsningen meget enkel:Indsæt parametrene i interne variabler og brug disse i din forespørgsel i stedet for. Jeg gjorde dette med min rapport, og produktionsrapporten gik tilbage til 10 sekunder, ligesom udviklingsversionen gjorde i Visual Studio.
For at omgå parametersniffing for din første forespørgsel, vil du få det til at se sådan ud:
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;