在子查询中添加括号后,结果立即在应用程序中返回。
在 vb.net/aspx Web 应用程序中由 RS2005 调用时,运行缓慢:
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 @StartDate and @EndDate
and c.schoolid = @SchoolID
and std.GradeID=@GradeLevel
GROUP BY
c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName,
std.GradeID, gl.GradeLevel
ORDER BY
u.LName, sb.behaviorID
这运行得很快:
select a.teacherid, a.teacher,a.bxcount, a.behaviorid,a.behaviorname,a.gradeid, a.gradelevel
from (
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 @StartDate and @EndDate
and c.schoolid = @SchoolID
and std.GradeID=@GradeLevel
group by c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName, std.GradeID, gl.GradeLevel
) a
order by a.teacher, a.behaviorid
它们在 SQL Server Management Studio 的查询窗口中以相同的速度运行。为什么会有差异?谢谢。
最佳答案
您可能遇到过有 parameter sniffing 问题的查询,这与 Sql Server 如何尝试优化您的查询执行计划有关,但在涉及 Reporting Services 的情况下,它会完全搞砸并使其运行得非常缓慢。
我有一个报告案例,其中有两个复杂的查询,每个查询大约 150 行,但在我的开发环境中运行了 7 秒 - 整个报告用了不到 10 秒。但是,当部署到生产 SSRS 服务器时,报告耗时超过 7 分钟,并且经常超时,导致报告无法运行。
大多数有关此问题的信息都与存储过程相关。不要因为您没有使用存储过程而忽略这一点(就像我长期以来所做的那样);它也与直接的 Sql 查询非常相关。
因此,您看到的不同之处在于 Sql Server 正在创建两个非常不同的执行计划,因为这两个查询的结构不同。
幸运的是,解决方案非常简单:将参数放入内部变量并在查询中使用这些参数。我用我的报告做了这个,生产报告回到了 10 秒,就像 Visual Studio 中的开发版本一样。
要绕过第一个查询的参数嗅探,您可以使它看起来像这样:
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;
关于asp.net - 为什么在 Web 应用程序中由 Reporting Services 2005 调用时,第二个 T-SQL 查询的运行速度比第一个快得多,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16924144/