Možná jste narazili na dotaz, který má problém s čicháním parametrů, což souvisí s tím, jak se Sql Server snaží optimalizovat váš plán provádění dotazů, ale v případech, kdy je zapojena služba Reporting Services, to úplně zkazí a zpomalí běh.
Měl jsem případ se sestavou, která měla dva složité dotazy, každý o délce přibližně 150 řádků, ale která se v mém vývojovém prostředí spustila za 7 sekund – celá sestava trvala méně než 10 sekund. Při nasazení na produkční server SSRS však sestava trvala déle než 7 minut a často vypršel časový limit, takže sestavu nebylo možné spustit.
Většina informací o tomto problému o něm hovoří ve vztahu k uloženým procedurám. Nezavrhujte to, protože nepoužíváte uložené procedury (jako já po dlouhou dobu); je také velmi relevantní pro přímé dotazy SQL.
Rozdíl, který vidíte, je ten, že SQL Server vytváří dva velmi odlišné plány provádění, protože tyto dva dotazy jsou strukturovány odlišně.
Naštěstí je řešení velmi jednoduché:vložte parametry do interních proměnných a místo toho je použijte ve svém dotazu. Udělal jsem to se svou zprávou a zpráva o produkci se vrátila na 10 sekund jako vývojová verze ve Visual Studiu.
Chcete-li obejít sniffování parametrů pro váš první dotaz, vypadalo by to takto:
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;