9

我有一张表,里面有超过 100MM 的记录。该表有一个聚集索引和一个非聚集索引。

我可以在表上使用 T-SQL 运行基本计数,运行需要 1 秒。当我在存储过程中放入相同的精确计数查询时,它需要 12 秒才能运行。

我查看了标准查询和存储过程的执行计划,它们都使用非聚集索引。

我不确定为什么存储过程与标准查询相比如此缓慢。

我已经阅读了一些关于在这种情况下重新索引的内容,但我不确定我为什么需要这样做。此外,重新索引需要几个小时,所以我想确保它会起作用。

对此的任何帮助都会很棒。

谢谢

更新

这是存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE quickCount 

@sYID INT,
@eYID INT

AS
BEGIN

SET NOCOUNT ON;


    SELECT COUNT(leadID)
    FROM dbo.leads
    WHERE yearID >= @sYID
    AND yearID <= @eYID

END
GO

这是标准查询:

SELECT COUNT(leadID)
FROM leads
WHERE yearID >= 0
AND yearID <= 99

我确实尝试在没有参数的情况下运行它,并且 SP 运行得更快(1 秒)。所以我假设它与参数有关。

4

5 回答 5

16

尝试将您的 SP 更改为使用传入变量的本地副本。

就像是

ALTER PROCEDURE quickCount  

@sYID INT, 
@eYID INT 

AS 
BEGIN 

SET NOCOUNT ON; 
    DECLARE @Local_sYID INT, 
            @Local_eYID INT 
    SELECT  @Local_sYID = @sYID INT, 
            @Local_eYID = @eYID INT

    SELECT COUNT(leadID) 
    FROM dbo.leads 
    WHERE yearID >= @Local_sYID 
    AND yearID <= @Local_eYID 

END 

我之前发现由于参数嗅探,SP 运行速度会慢很多,但是一旦使用变量的副本,性能就会恢复。

什么是参数嗅探?

SQL Server:参数嗅探

于 2012-10-22T05:02:54.270 回答
4

如前所述,这可能是参数嗅探问题。尝试包括以下行:

OPTION (RECOMPILE)

在您的 SQL 查询结束时。

这里有一篇文章解释什么是参数嗅探:http: //blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

于 2014-01-22T16:44:50.353 回答
1

您总是可以尝试将其作为动态 sql 执行:

ALTER PROCEDURE quickCount  

@sYID INT, 
@eYID INT 

AS 
BEGIN 
    SET NOCOUNT ON;

    DECLARE @SQL VARCHAR(max)

    SELECT @SQL = '
    SELECT COUNT(leadID) 
    FROM dbo.leads 
    WHERE yearID >= '+CONVERT(VARCHAR(20),@sYID)+'
    AND yearID <=   '+CONVERT(VARCHAR(20),@eYID)

    EXEC (@SQL)
END 
于 2012-10-22T06:57:30.797 回答
0

第一次运行存储过程时,SQL Server 必须编译存储过程,这可能需要一些时间。@Astander 提到了参数嗅探——这是一个有效的观点,并且可能会扭曲您的结果。

其他一些需要考虑的因素是(虽然它们不应该真正解释你的症状):

  • 您可以强制锁定级别,例如WITH (NOLOCK)在表名之后,这可以解决问题(但请注意,这样做可能会得到不准确的结果)。
  • 您可能需要更新表上的统计信息或对索引进行碎片整理
于 2012-10-22T20:25:52.377 回答
0
EXEC sp_recompile N'dbo.MyStoredProc';

为我做了诀窍。存储过程需要 13 秒才能运行,查询需要 0.00 秒。运行上述命令后,它们都需要 0.00 秒 :)

于 2020-12-04T01:13:50.800 回答