我知道 SQL Server 2005 会缓存一些执行计划,但这是否足以在同一查询运行两次之间产生小时差异?第一次需要3小时下次需要1分钟?这甚至可能吗?
4 回答
SQL Server 不仅会缓存执行计划,还会缓存数据
如果你这样做
设置统计 IO 开启
并查看输出,您将看到逻辑读取和物理读取,逻辑读取来自 RAM,物理读取来自磁盘。所以第一次你会看到一个物理读取的数字,而如果你再次运行它,你应该会看到一个逻辑读取的值
3 小时似乎很长,也可能是因为阻塞/锁定、过时的统计信息等
不!没有机会!
区别在别处!
提出查询计划的时间最多是几秒钟(更糟)。
差异很可能是由于以下任一原因:
- 缓存数据
- 来自其他查询/进程的锁的存在/不存在
- 第二次运行查询时的不同数据上下文(引用的 SQL 对象较少的行等)
提到的差异:3小时,下降到1分钟左右是如此剧烈,我认为仅缓存数据无法解释它。
这就是获得有关查询的更多信息会有所帮助的地方......
例如,即使它是相同的查询运行了两次,它在第二次时可能会有不同的行为(例如,如果这是一个更新/插入/删除类型查询,可能不需要修改这么多行)。即使是仅 SELECT 查询也可能会以不同的方式运行,因为基础数据已被修改(由其他查询/进程)。
这里有一些建议可以帮助您了解更多信息:
- 检查(静态)执行计划本身。看看里面是否确实有一些东西可能会花费 3 个小时。
- 使用“statistics on”重新运行查询,并在每次运行前清除(或不清除)缓存。
清除缓存的语句是(可能有其他方法可以使用较新版本的 SQL-Server):
dbcc freeproccache
go
dbcc dropcleanbuffers
go
从理论上讲,当第一次运行(“冷运行”)时,您的查询所需的表和索引页可能已经位于磁盘上。查询获取它们并且引擎将它们放入缓存中。
查询的第二次运行(“热运行”)仅使用缓存中的数据,这当然要快得多。
但是,即使是最大的缓存,3 小时也绰绰有余,所以这几乎不可能。
最有可能的是,第二次运行时使用了另一个执行计划(可能是由于统计信息更新)。
不会。您的查询很可能第一次被阻止(例如,被另一个会话或增长事件阻止),而第二次则没有。
举个例子,以这个查询为例:INSERT INTO Table (Field) VALUES (1)
。简单的查询,但是当您第一次运行它时,数据库已满并且必须增长。数据库是 750GB,默认增长 10%,所以它必须创建 75GB,因为 SQL Server 服务帐户没有被授予执行卷维护任务,所以增长持续了大约 30 分钟。然后你再次运行查询,它需要不到一秒钟的时间。
Point here is not that you had or had not a growth event occurring during execution. Point is that if the query lasts 3 hours, you need to understand why. Activity Monitor is a great start. Reading up a white paper like Performance Tunning Wait Queues would be even better.