今天,我遇到了一个存储过程在从 ASP.NET 网页运行时超时(耗时超过 30 秒)的问题,但在从 SSMS 运行时却快速执行(耗时 5 秒)。
在怀疑参数嗅探是罪魁祸首之后,我屏蔽了输入参数,查询执行得更快。
我的问题是:为什么会这样?
这个系统已经投入生产超过 5 年,这是我们第一次在我们的存储过程中看到这样的东西。这是“数据库磨损”吗?
我们已经解决了这个问题,所以这没什么大不了的,但我只是好奇为什么会这样。
今天,我遇到了一个存储过程在从 ASP.NET 网页运行时超时(耗时超过 30 秒)的问题,但在从 SSMS 运行时却快速执行(耗时 5 秒)。
在怀疑参数嗅探是罪魁祸首之后,我屏蔽了输入参数,查询执行得更快。
我的问题是:为什么会这样?
这个系统已经投入生产超过 5 年,这是我们第一次在我们的存储过程中看到这样的东西。这是“数据库磨损”吗?
我们已经解决了这个问题,所以这没什么大不了的,但我只是好奇为什么会这样。
基本上发生的情况是,当 SQL Server 看到需要编译的查询时,它将使用首次调用的参数来生成执行计划。这可能是也可能不是一件好事,但这就是发生的事情。
例如,假设您有一张水果表(100 行)。有 98 行是苹果,只有 2 行是橙子。如果您在该表中查询 Apple,那么该计划很可能会通过 Scan 进行编译。这是一件好事,因为它针对 Apple 查询进行了优化。但是,当您要查询 Orange 时,该 Scan 效率低下。但正在使用的是存储的计划。
事实是它发生了。它一直在发生。这通常不是一个突出的问题,但在某些情况下它可能是一个相当大的问题。一个持续的错误参数嗅探问题的解决方案是,您可以利用
OPTIMIZE FOR
查询提示强制 SQL Server 在初始编译时生成执行计划时使用某些参数值。相当烦人的是,SSMS 默认是针对
SET ARITHABORT ON
大多数客户端库(ADO .Net、ODBC、OLE DB)指定SET ARITHABORT OFF
. 您可能有一个“变坏”的计划,但是当您尝试通过 SSMS 进行复制时,ARITHABORT 的差异导致使用了不同的计划,这是“好的”。应用程序慢,SSMS 快?是一个很好的参考。
很可能触发了重新编译,不幸的是,一组非典型的输入被用于编译。