我有一个奇怪的情况,我不太确定我的SQL Server 2016中的存储过程发生了什么。
我创建了两个相同的程序,如下所示:
create procedure [dbo].[zsp_select_Transactions]
(@SearchedUserId int,
@StartDate datetime,
@EndDate datetime)
as
select
et.TransactionID, et.QuantityPurchased,
et.SalePrice, et.ItemID, et.Title
from
Transactions et
where
et.SearchedUserID = @SearchedUserId
and et.TransactionDate between @StartDate and @EndDate
order by
et.TransactionDate desc
第二个存储过程看起来完全一样,但它只有一个不同的名称zsp_select_Transactions2
zsp_select_Transactions
程序当前被大量用户使用,并且每秒都在执行。
我试图在我的服务器的SQL Server Management Studio上运行这样的程序:
exec zsp_select_Transactions 75559,'2017-12-25','2018-01-25'
和
exec zsp_select_Transactions2 75559,'2017-12-25','2018-01-25'
请注意执行程序的名称差异......
这两个人的结果让我完全震惊,我意识到我在这里错过了一些......
第一个程序(所有用户都在使用,可能每秒钟就有1000个用户)需要30秒才能获取结果,而第二个程序zsp_select_Transactions2
只需要1秒!
我很震惊地看到这样不同的结果,但我只能猜测这是由于许多用户每秒执行第一个程序?
当我在本地PC上测试程序时,我的执行时间几乎相同,就像zsp_select_Transactions2
程序一样......
我在这里错过了什么?有人可以帮助我吗?
答案 0 :(得分:2)
"参数嗅探"问题。 Parameter Sniffing Problem and Possible Workarounds:
SQL Server使用(嗅探)第一次编译过程时发送的参数编译存储过程并将其放入计划缓存中。之后,每次再次执行该过程时,SQL Server都会从缓存中检索执行计划并使用它(除非有重新编译的原因)。
第一次执行存储过程时会出现潜在问题,参数集会为该组参数生成可接受的计划,但对其他更常见的参数集非常不利。
有一些解决方法可以解决这个问题。
OPTION (RECOMPILE)
OPTION (OPTIMIZE FOR (@VARIABLE=VALUE))
OPTION (OPTIMIZE FOR (@VARIABLE UNKNOWN))
Use local variables
使用第一种选择:
create procedure [dbo].[zsp_select_Transactions]
(@SearchedUserId int,
@StartDate datetime,
@EndDate datetime)
as
select
et.TransactionID, et.QuantityPurchased,
et.SalePrice, et.ItemID, et.Title
from
Transactions et
where
et.SearchedUserID = @SearchedUserId
and et.TransactionDate between @StartDate and @EndDate
order by
et.TransactionDate desc
option (recompile);