Być może natknąłeś się na zapytanie, które ma problem z podsłuchiwaniem parametrów, co ma związek ze sposobem, w jaki Sql Server próbuje zoptymalizować plan wykonywania zapytań, ale w przypadkach, gdy zaangażowane są usługi Reporting Services, całkowicie je psuje i sprawia, że działa ono niezwykle wolno.
Miałem przypadek z raportem, który zawierał dwa złożone zapytania po około 150 linii każde, ale które działały w ciągu 7 sekund w moim środowisku programistycznym - cały raport zajął mniej niż 10 sekund. Jednak po wdrożeniu na produkcyjnym serwerze SSRS raport zajmował ponad 7 minut i często przekraczał limit czasu, przez co nie można było uruchomić raportu.
Większość informacji o tym problemie mówi o tym w odniesieniu do procedur składowanych. Nie odrzucaj tego, ponieważ nie używasz procedur przechowywanych (tak jak ja przez długi czas); jest to również bardzo istotne w przypadku prostych zapytań SQL.
Różnica, którą widzisz, polega na tym, że SQL Server tworzy dwa bardzo różne plany wykonania, ponieważ te dwa zapytania mają inną strukturę.
Na szczęście rozwiązanie jest bardzo proste:umieść parametry w zmiennych wewnętrznych i użyj ich w zapytaniu. Zrobiłem to z moim raportem, a raport produkcyjny cofnął się do 10 sekund, tak jak wersja rozwojowa zrobiła w Visual Studio.
Aby ominąć wąchanie parametrów dla pierwszego zapytania, możesz sprawić, by wyglądało to tak:
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;