Bạn có thể đã gặp phải một truy vấn có vấn đề với việc dò tìm tham số, điều này liên quan đến cách Sql Server cố gắng tối ưu hóa kế hoạch thực thi truy vấn của bạn nhưng trong các trường hợp khi Dịch vụ báo cáo có liên quan hoàn toàn làm rối tung nó và làm cho nó chạy cực kỳ chậm.
Tôi đã gặp trường hợp với một báo cáo có hai truy vấn phức tạp, mỗi truy vấn khoảng 150 dòng nhưng chạy trong 7 giây trong môi trường phát triển của tôi - toàn bộ báo cáo chỉ mất chưa đầy 10 giây. Tuy nhiên, khi được triển khai tới máy chủ SSRS sản xuất, báo cáo mất hơn 7 phút và thường hết thời gian khiến báo cáo không thể chạy được.
Hầu hết thông tin về vấn đề này nói về nó liên quan đến các thủ tục được lưu trữ. Đừng loại bỏ điều này bởi vì bạn không sử dụng các thủ tục được lưu trữ (như tôi đã làm trong một thời gian dài); nó cũng rất liên quan đến các truy vấn Sql.
Vì vậy, sự khác biệt mà bạn đang thấy là Sql Server đang tạo hai kế hoạch thực thi rất khác nhau vì hai truy vấn được cấu trúc khác nhau.
May mắn thay, giải pháp rất đơn giản:đặt các tham số vào các biến bên trong và thay vào đó sử dụng chúng trong truy vấn của bạn. Tôi đã làm điều này với báo cáo của mình và báo cáo sản xuất quay trở lại 10 giây giống như phiên bản phát triển đã làm trong Visual Studio.
Để bỏ qua tính năng dò tìm tham số cho truy vấn đầu tiên của bạn, bạn sẽ làm cho nó trông giống như sau:
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;