我在SQL Server 2008中有一个sproc。它基本上构建一个字符串,然后使用EXEC()运行查询:
SELECT * FROM [dbo].[StaffRequestExtInfo] WITH(nolock,readuncommitted)
WHERE [NoteDt] < @EndDt
AND [NoteTypeCode] = @RequestTypeO
AND ([FNoteDt] >= @StartDt AND [FNoteDt] <= @EndDt)
AND [FStaffID] = @StaffID
AND [FNoteTypeCode]<>@RequestTypeC
ORDER BY [LocName] ASC,[NoteID] ASC,[CNoteDt] ASC
除了@RequestTypeO和@RequestTypeF之外的所有内容都作为sproc参数传入。另外两个是从参数构建到局部变量。通常,查询运行不到一秒钟。但是,对于@StaffID的一个特定值,执行计划是不同的,大约慢30倍。在任何一种情况下,返回的数据量通常都是相同的,但执行时间会逐渐增加。
我试图重新编译sproc。我还尝试将@StaffID“复制”到本地@LocalStaffID中。这两种方法都没有任何区别。
有什么想法吗?
更新:尝试使用以下方式删除特定计划:
DECLARE @ph VARBINARY(64), @pt VARCHAR(128), @sql VARCHAR(1024)
DECLARE cur CURSOR FAST_FORWARD FOR
SELECT p.plan_handle
FROM sys.[dm_exec_cached_plans] p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) t
WHERE t.text LIKE N'%cms_selectStaffRequests%'
OPEN cur
FETCH NEXT FROM cur INTO @ph
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @pt = master.dbo.fn_varbintohexstr(@ph)
PRINT 'DBCC FREEPROCCACHE(' + @pt + ')'
SET @sql = 'DBCC FREEPROCCACHE(' + @pt + ')'
EXEC(@sql)
FETCH NEXT FROM cur INTO @ph
END
CLOSE cur
DEALLOCATE cur
错误的计划被删除,或者同样的计划最终被重建,但它没有效果。
答案 0 :(得分:0)
检查列FStaffID中值的分布/频率/基数,并检查索引。可能有一个工作人员做了50%的工作(可能是DBA :),这可能会改变优化器选择使用哪些索引以及如何读取数据的方式。
或者,动态代码生成的执行计划可能正在保存和重新使用,导致执行效果不佳(如HLGEM所说)。我不了解细节,但SQL 2008有更多的方法让你在做这件事时比你的前辈迷惑。
答案 1 :(得分:0)
在查询的主基表上执行UPDATE STATISTICS ... WITH FULLSCAN
会导致“慢”值与慢速计划无关。