存储过程在首次运行时执行缓慢

时间:2010-10-25 01:27:56

标签: sql sql-server sql-server-2005 tsql

创建了一个用于监控网站目的的存储过程。

首次运行时,该过程需要一分钟才能执行,如果在此之后不久运行,则只需几秒钟即可运行。问题是该脚本计划以十分钟为间隔运行,每次运行时都需要一分钟,这太长了。

是否有人知道如何改善此查询的效果?我知道有一个原因是它第一次运行缓慢,然后很快就会发生任何后续但却无法找到答案。

这是代码,提前谢谢:)

SET NOCOUNT ON
SET DATEFORMAT ymd

declare @start datetime
declare @end datetime
set @start = DATEADD(dd,-1,GETDATE())
set @end = GETDATE()

declare @errorToday int
declare @unconfirmedToday int

set @unconfirmedToday = 
(
 SELECT COUNT([DateCreated])
 FROM GenericLeadLogs WITH(NOLOCK)
 WHERE DestinationConfirmation IS NULL 
 AND [DateCreated] BETWEEN @start AND @end
)

SET @errorToday = 
(
 SELECT COUNT([DateCreated])
 FROM GenericLeadLogs WITH(NOLOCK)
 WHERE Severity = 'Error' 
 AND [DateCreated] BETWEEN @start AND @end
)

CREATE TABLE #GenericLeadStats 
(
 UnconfirmedToday int null, 
 ErrorToday int null
)

INSERT INTO #GenericLeadStats (UnconfirmedToday, ErrorToday)
values(@unconfirmedToday, @errorToday)

SELECT * FROM #GenericLeadStats
DROP TABLE #GenericLeadStats 

3 个答案:

答案 0 :(得分:4)

我将存储过程重写为:

SET NOCOUNT ON

SELECT SUM(CASE WHEN DestinationConfirmation IS NULL THEN 1 ELSE 0 END) AS unconfirmedToday,
       SUM(CASE WHEN Severity = 'Error' THEN 1 ELSE 0 END) AS errorToday
  INTO #GenericLeadStats
  FROM GenericLeadLogs WITH(NOLOCK) 
 WHERE [DateCreated] BETWEEN DATEADD(dd,-1,GETDATE()) AND GETDATE()

SELECT * FROM #GenericLeadStats

DROP TABLE #GenericLeadStats 

在SQL Server中,SELECT INTO子句创建一个尚不存在的表。我要离开了,但根据所提供的内容,它没有用处。

答案 1 :(得分:2)

通常,数据库存储在磁盘上。但是,在所有现代操作系统上,读取后的文件通常都缓存在内存中。查询运行缓慢的原因是正在从磁盘读取数据。在第一次查询之后,重新执行查询所需的大部分数据(如果不是全部)都被缓存,并且不需要实际从磁盘读取(慢速)。经过一段时间后,如果机器用于其他目的或运行其他查询,数据将从缓存中移出以为新数据腾出空间,因此只要需要重新读取数据,查询就会再次变慢来自磁盘。

您应该确保上面的was语句中的所有列都有索引。我假设已经完成了?如果是,则检查查询计划以查看它们是否正在使用。最后,如果表格非常大,您可以考虑对其进行分区,如果这对您的数据模型有意义的话。

答案 2 :(得分:1)

查看您的查询我看不出会导致大量性能问题的明显错误 - 第二次查询更快的原因似乎只是因为所需的数据仍然被缓存,在这种情况下你无能为力。

您应该获取执行计划并可能通过查询优化器运行查询以查看是否缺少任何索引 - 如果您缺少任何索引,这可能有助于提高查询的性能。