当我第一次运行某个存储过程时,大约需要2分钟才能完成。当我第二次运行时,它在大约15秒内完成。我假设这是因为在第一次运行后所有内容都被缓存了。在我第一次运行此程序之前,我是否可以“加热缓存”?缓存的信息是仅在我再次使用相同的参数调用相同的存储过程时使用的,还是在我使用不同的参数调用相同的存储过程时使用?
答案 0 :(得分:9)
执行查询时,数据将以块的形式读入内存。这些块保留在内存中,但它们会“老化”。这意味着块被标记为最后一次访问,并且当Sql Server需要另一个块用于新查询并且内存缓存已满时,最近最少使用的块(最旧的)被踢出内存。 (在大多数情况下 - 全表扫描块会立即老化,以防止全表扫描超出内存并阻塞服务器)。
这里发生的事情是,第一个查询的内存中的数据块还没有被踢出内存,因此可以用于第二次查询,这意味着可以避免磁盘访问并提高性能。
所以你的问题实际问的是“我可以将我需要的数据块放入内存而不将其读入内存(实际上是在进行查询)吗?”答案是否定的,除非您想要缓存整个表并将它们永久驻留在内存中,从您描述的查询时间(以及数据大小)开始,可能不是一个好主意。
性能改进的最佳选择是查看查询执行计划,看看更改索引是否可以提供更好的结果。有两个主要方面可以改善绩效:
答案 1 :(得分:3)
我认为生成执行计划的费用不会超过1秒。
我认为第一次和第二次运行之间的差异是由缓存内存中的数据引起的。
任何进一步的查询(存储过程或简单选择)都可以重用高速缓存中的数据。
您可以通过读取相同数据的任何选择来读取数据,从而“加热”缓存。但这也会花费大约90秒。
答案 2 :(得分:2)
您可以检查执行计划以找出查询使用的表和索引。然后,您可以执行一些SQL以将数据放入缓存中,具体取决于您所看到的内容。
SELECT * FROM my_big_table
即可强制所有表的数据页进入缓存。SELECT first_column_in_index FROM my_big_table
。要强制加载特定索引,您还可以在缓存预热查询中使用WITH(INDEX(index))
表提示。
答案 3 :(得分:0)
从光盘读取的SQL Server缓存数据。 连续读取将减少IO。 这是非常有用的,因为磁盘IO通常是瓶颈。
答案 4 :(得分:-1)
执行计划(程序的缓存信息)每次都会重复使用,即使参数不同也是如此。这是使用存储过程的好处之一。
第一次执行存储过程时,SQL Server会生成执行计划并将其放入过程高速缓存中。
对数据库的某些更改可能会触发执行计划的自动更新(您也可以明确要求重新编译)。
执行计划根据其“年龄”从过程缓存中删除。 (来自MSDN:不经常引用的对象很快就可以解除分配,但实际上不会被释放,除非其他对象需要内存。)
我不认为有任何方法可以“加热缓存”,除了执行存储过程一次。这将保证缓存中有执行计划,任何后续调用都将重用它。
MSDN文档中提供了更详细的信息:http://msdn.microsoft.com/en-us/library/ms181055(SQL.90).aspx