パラメータスニッフィングに問題があるクエリに遭遇した可能性があります。これは、SQL Serverがクエリ実行プランを最適化しようとする方法に関係していますが、Reporting Servicesが関与している場合は、クエリが完全に台無しになり、実行が非常に遅くなります。
それぞれ約150行の2つの複雑なクエリが含まれているが、開発環境では7秒で実行されたレポートのケースがありました。レポート全体の所要時間は10秒未満でした。ただし、本番SSRSサーバーにデプロイすると、レポートに7分以上かかり、タイムアウトしてレポートを実行できなくなることがよくありました。
この問題に関するほとんどの情報は、ストアドプロシージャに関連して問題について説明しています。ストアドプロシージャを使用していないため、これを却下しないでください(私が長い間使用していたように)。ストレートSQLクエリにも非常に関連しています。
したがって、表示されている違いは、2つのクエリの構造が異なるため、SQLServerが2つの非常に異なる実行プランを作成していることです。
幸い、解決策は非常に単純です。パラメーターを内部変数に入れ、代わりにこれらをクエリで使用します。私は自分のレポートでこれを行い、本番レポートはVisualStudioの開発バージョンと同じように10秒に戻りました。
最初のクエリのパラメータスニッフィングをバイパスするには、次のようにします。
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;