2010-01-04 103 views
9

当我第一次运行某个存储过程时,大约需要2分钟才能完成。当我第二次运行它时,它在大约15秒内完成。我假设这是因为在第一次运行后所有内容都被缓存了。在我第一次运行此程序之前,是否可以“预热缓存”?只有当我再次调用具有相同参数的存储过程时,才会使用缓存的信息,或者如果我使用不同的参数调用相同的存储过程,是否会使用缓存的信息?SQL Server缓存问题

回答

9

当您执行查询时,数据以块的形式读入内存。这些块保留在内存中,但它们会“老化”。这意味着这些块被标记为上次访问,并且当Sql Server需要另一个块用于新查询并且内存缓存已满时,最近使用最少的块(最早的块)被踢出内存。 (在大多数情况下 - 全表扫描块会立即老化以防止全表扫描超出内存并窒息服务器)。

这里发生的事情是,在从第一查询内存中的数据块尚未被踢出的记忆却又如此可用于你的第二个查询,这意味着接盘,避免和性能的提高。

那么你的问题是真正问的是“我能得到我需要到内存中的数据块,而不读取它们到内存(实际做一个查询)?”。答案是否定的,除非你想缓存整个表,并让它们永久驻留在内存中,从描述的查询时间(以及数据大小)来看,这可能不是一个好主意。

你对性能的改善最好的办法是看你的查询执行计划,看是否改变你的索引可能会给一个更好的结果。有迹象表明,可以在这里提高性能的两个主要方面:

  • 创建索引,其中查询可以使用一个避免低效的查询和全表扫描
  • 添加更多的列的索引,以避免第二盘读取。例如,您有一个查询返回列A和B,并在A和C上具有where子句,并且您在列A上有一个索引。您的查询将使用列A的索引,要求读取一个磁盘,但需要第二个磁盘命中以获得列B和C.如果索引中包含所有列A,B和C,则可以避免第二个磁盘命中以获取数据。
-1

即使使用不同的参数,执行计划(您的过程的缓存信息)也会每次重复使用。这是使用存储过程的好处之一。

第一次执行存储过程时,SQL Server会生成执行计划并将其放入过程高速缓存中。

数据库的某些更改可能会触发执行计划的自动更新(并且您也可以明确要求重新编译)。

执行计划将根据其“年龄”从过程缓存中删除。 (来自MSDN:很少被引用的对象很快就有资格取消分配,但实际上并没有解除分配,除非其他对象需要内存。)

我不认为有任何方法可以“加热缓存”,除了执行存储过程一次。这将保证高速缓存中有一个执行计划,随后的任何调用都会重用它。

更详细的信息MSDN文档中获得:http://msdn.microsoft.com/en-us/library/ms181055(SQL.90).aspx

+4

您的回复,但我看不出什么毛病,不得要领。查询编译不需要1分45秒,所以这不是OP的问题。 OP缓存问题与数据页缓存有关,而不是执行计划缓存。 – erikkallen 2010-01-04 22:50:31

3

我不认为生成执行计划将花费更多的1秒。

我相信第一次和第二次运行之间的区别是由内存中的数据缓存引起的。

缓存中的数据可以被任何进一步的查询(存储过程或简单选择)重用。

您可以通过读取相同数据的任何选择来读取数据来“加热”缓存。但是,这甚至会花费大约90秒。

2

您可以检查执行计划以找出您的查询使用哪些表和索引。然后,您可以执行一些SQL以将数据存入缓存,具体取决于您看到的内容。

  • 如果您看到聚簇索引seek,那么可以简单地执行SELECT * FROM my_big_table以强制所有表的数据页进入高速缓存。
  • 如果看到非聚集索引搜索,则可以尝试SELECT first_column_in_index FROM my_big_table

要强制加载特定索引,还可以在缓存热身查询中使用WITH(INDEX(index))表提示。