【问题标题】:Stored procedure in SQL Server performs very slowly when used by many usersSQL Server 中的存储过程在被许多用户使用时执行非常缓慢
【发布时间】:2018-07-06 06:45:51
【问题描述】:

我有一个奇怪的情况,我不太确定我的 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 中测试该过程时,我得到了几乎相同的 1 秒执行时间,就像 zsp_select_Transactions2 过程...

我在这里错过了什么?有人可以帮帮我吗?

【问题讨论】:

  • 简短回答:可能。长答案:您真的需要ORDER BY吗?
  • 你是真的只尝试过一次,还是多次尝试都一样?
  • @JacobH 好吧,不,不是真的......但是我真的有可能仅仅因为它被许多用户执行而无法避免这个性能问题吗?也许通过缓存它或类似的东西? =(
  • @JoePhillips 有时我会在第一个上得到更糟糕的结果 =(
  • 原来没有使用新索引。它使用如此频繁,缓存计划永不过期,因此永远不会创建具有新索引的新计划。重新运行 create 语句,您将使计划无效,然后将在知道新索引的情况下创建一个新的。

标签: sql-server performance sql-server-2008 tsql stored-procedures


【解决方案1】:

这是“参数嗅探”问题。 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多