2012-10-22 92 views
8

我有一张超过100MM记录的表。该表具有聚簇索引和非聚簇索引。SQL Server存储过程比直接查询要慢很多

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

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

我不知道为什么存储过程与标准查询相比太慢了。

我已经阅读了一些关于在这种情况下重新索引的东西,但我不知道为什么我需要这样做。另外,重新索引需要几个小时,所以我想确保它能正常工作。

对此的任何帮助将是伟大的。

感谢

UPDATE

这里是存储过程:

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秒)。所以我假设它与参数有关。

+1

您能不能告诉我们一些SP的,母鹿你在任何参数传递? –

+0

我认为你需要展示你的查询和SP。 –

+1

可能发生的情况是,您尝试使用常量进行查询,并且您的过程使用参数而不是此常量。我建议你创建SQLFiddle示例或发布一些关于模式和查询的详细信息/ sp –

回答

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 

我已经在此之前,发现由于参数Snffing,一个SP可以运行慢了很多,但一旦您使用变量的副本,性能就会返回。

What is Parameter Sniffing ?

SQL Server : Parameter Sniffing

+0

感谢您的帮助,但我已经尝试过。这并没有让它变得更快。 – Sequenzia

+1

哇!感谢那!直到找到这篇文章,我才找到SP中的问题!非常感谢! – artsylar

+0

@Sequenzia谢谢 –

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 
0

运行存储过程中的第一次,SQL Server将不得不编译存储过程,这可能需要一些时间。 @Astander提到参数嗅探 - 这是一个有效的观点,并且可能会歪曲你的结果。

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

  • 你可以强制锁定的水平,例如, WITH (NOLOCK)之后的表名称,它可以解决问题(但请注意,您可以通过这样做得到不准确的结果)。
  • 您可能需要更新表上的统计或整理索引