Vous avez peut-être rencontré une requête qui a un problème avec le reniflage des paramètres, qui a à voir avec la façon dont Sql Server essaie d'optimiser votre plan d'exécution de requête, mais dans les cas où Reporting Services est impliqué, il le gâche complètement et le fait fonctionner incroyablement lentement.
J'ai eu un cas avec un rapport contenant deux requêtes complexes d'environ 150 lignes chacune mais qui s'exécutaient en 7 secondes dans mon environnement de développement - l'ensemble du rapport prenait moins de 10 secondes. Cependant, lorsqu'il était déployé sur le serveur SSRS de production, le rapport prenait plus de 7 minutes et expirait souvent, ce qui rendait le rapport inexécutable.
La plupart des informations sur ce problème en parlent en relation avec les procédures stockées. Ne rejetez pas cela parce que vous n'utilisez pas de procédures stockées (comme je l'ai fait pendant longtemps); il est également très pertinent pour les requêtes SQL directes.
La différence que vous voyez est donc que Sql Server crée deux plans d'exécution très différents car les deux requêtes sont structurées différemment.
Heureusement, la solution est très simple :placez les paramètres dans des variables internes et utilisez-les dans votre requête à la place. Je l'ai fait avec mon rapport et le rapport de production est revenu à 10 secondes comme la version de développement l'a fait dans Visual Studio.
Pour contourner le reniflage de paramètres pour votre première requête, vous devez la faire ressembler à ceci :
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;