我们有一个使用 Microsoft SQL 数据库的现成应用程序。在此应用程序中,我们为每个报告挑选各种选择标准。该应用程序然后运行这些报告。
我相信我们有一个查询计划问题。我们每天运行的第一份报告,运行速度非常快 7 分钟。我们在第一份报告之后运行的任何报告都需要一个多小时。
每天晚上我们都会运行一个计划任务来停止和启动 SQL Server 代理和 SQL Server。在这一 SQL Server 实例中大约有 25 个其他数据库。没有其他数据库有性能问题,只有我之前提到的现成产品。
有没有办法清除 SQL Server 当前在内存中的所有查询计划?
如何在不影响依赖同一服务器上其他数据库的 30 个左右的用户的情况下做到这一点?
你在这里问了两个问题。首先,您想知道是否可以删除存储在内存中的 SQL 实例的所有计划。正如 Matt M 所建议的,这是使用 DBCC FREEPROCCACHE 完成的。
您问的第二个问题是“我怎样才能做到这一点而不影响依赖同一服务器上其他数据库的 30 名左右的用户?”。简短的回答是“你不能”。如果您删除所有计划而不是依赖计划在内存中的其他用户可能会受到性能影响。
解决此问题的方法需要一些手动干预。如果您有 plan_handle,您可以使用 DBCC FREEPROCCACHE 删除特定计划。
从您上面描述的内容来看,这听起来确实像是一个计划问题,但我不确定删除计划是否就是答案。在考虑删除计划之前,我会向您指出参数嗅探的方向:
关联
您应该能够优化查询,而不是按计划使用 DBCC FREEPROCCACHE。我还建议您花时间分析您的实例的等待事件。
DBCC FREEPROCCACHE
使用此命令,您可以将整个过程缓存清除为单个命令。在使用此命令之前一定要阅读文档。多读几遍备注部分。
清除过程缓存将导致存储过程缓存在下次使用时重新编译。这可能会影响性能。谨慎使用!
马特
我为我之前的回答道歉。
1) 如果您知道每次从存储过程运行查询都会发生变化,则将 WITH RECOMPILE 选项添加到 CREATE PROCEDURE 语句。WITH RECOMPILE 选项可防止重用存储过程执行计划,因此 SQL Server 不会缓存此过程的计划,并且会在运行时重新编译该过程。如果您的查询每次从存储过程运行时都会发生变化,那么使用 WITH RECOMPILE 选项可以提高性能,因为在这种情况下不会使用错误的执行计划。
2)您必须创建一个计划指南,该指南对每种查询类型(每种存储过程请求类型)使用 USE PLAN 查询提示来强制执行计划。
这是有关可以提供帮助的执行计划的文章。