Mogelijk bent u een query tegengekomen die een probleem heeft met het snuiven van parameters, wat te maken heeft met hoe Sql Server uw plan voor het uitvoeren van query's probeert te optimaliseren, maar in gevallen waarin Reporting Services erbij betrokken is, verknoeit het volledig en laat het ongelooflijk langzaam werken.
Ik had een casus met een rapport met twee complexe queries van elk ongeveer 150 regels, maar dat in mijn ontwikkelomgeving in 7 seconden liep - het hele rapport duurde minder dan 10 seconden. Bij implementatie op de SSRS-productieserver duurde het rapport echter meer dan 7 minuten en trad er vaak een time-out op, waardoor het rapport onuitvoerbaar werd.
De meeste informatie over dit probleem gaat erover in relatie tot opgeslagen procedures. Negeer dit niet omdat u geen opgeslagen procedures gebruikt (zoals ik lange tijd deed); het is ook zeer relevant voor rechte SQL-query's.
Dus het verschil dat u ziet, is dat Sql Server twee zeer verschillende uitvoeringsplannen maakt, omdat de twee query's anders zijn gestructureerd.
Gelukkig is de oplossing heel eenvoudig:plaats de parameters in interne variabelen en gebruik deze in plaats daarvan in uw query. Ik deed dit met mijn rapport en het productierapport ging terug naar 10 seconden zoals de ontwikkelingsversie deed in Visual Studio.
Als u het snuiven van parameters voor uw eerste zoekopdracht wilt omzeilen, ziet u deze er als volgt uit:
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;