我有一个包含数百万行的表,我需要不时从中运行一些查询。第一个查询通常会很慢(大约 10 秒),随后的查询通常会更快(大约 1 秒)。几个小时后,一个缓慢/然后快速的循环再次开始。
我已经在我的执行计划中检查了所有需要的索引都存在并得到了适当的使用,我认为性能差异是由于索引实际上在内存中用于后续查询(我是对的,还是有其他可能的原因?)
我还使用索引运行了许多其他查询,但这些查询耗时较少,性能也不那么重要,所以我担心这些索引实际上是将我的关键索引从内存缓存中推出。
除了明显的“添加更多 RAM”修复之外,我一直在考虑编写虚拟查询脚本,使其每小时运行一次,以强制索引返回内存。
有没有更优雅的方法来做到这一点?就像暗示 SQLServer 的一种方式,如果它只有足够的内存来保持一个索引缓存,它应该是那个?
我知道通常最好的办法是不要在这类事情上搞砸 SQLServer,但是我的查询的不寻常性质(很少运行,但对时间要求严格)让我相信它是有意义的(如果可能的话) .
我也很想知道是否有办法知道在给定时间哪些索引缓存在内存中?
我修改了数据库中的一个中央表,sp_depends 确实返回了数百个结果,我担心其中一些存储过程在我更改后可能不再编译。
检查单个存储过程很容易(我只是重新运行alter 脚本并查看操作是否成功),但是对100 多个过程执行此操作有点麻烦。
我知道我可以使用脚本像这样一个重新编译我的数据库中的所有对象,但实际操作中会发生下一次的存储过程执行,而不是立即,这样似乎并不在我的情况适合。
我还想我可以完全删除所有的存储过程,并用我的源代码控制系统重新同步我的数据库,但是这个选项虽然可行,但不是很优雅。有没有更好的方法来做到这一点?
我使用的是 SQLServer 2008 R2,我的数据库脚本存储在 VS 2008 数据库项目中。
澄清一下,我并不是主张人们应该仅仅依靠这种方法来测试代码。就像在 c# 中一样,您在编写代码时会立即检测其他依赖文件中的语法错误(然后使用其他策略进行测试,例如单元测试,这通常会慢几个数量级),我认为检测 SQL 依赖关系是有意义的在几秒钟内出错,而不必运行通常需要几个小时才能完成的完整功能测试。
我有一个非常基本的触发器定义如下:
CREATE TRIGGER dbo.foo
ON dbo.bar
FOR INSERT, UPDATE, DELETE
AS
...
Run Code Online (Sandbox Code Playgroud)
我还有一个存储过程,它在某些时候会做这样的事情:
Insert into dbo.bar (a) select a from @bar
Run Code Online (Sandbox Code Playgroud)
当@bar 包含一些数据时,我的触发器会按预期调用,但当它不包含时,即使 dbo.bar 显然没有更改,也会调用触发器。
SQL 探查器和 sys.dm_exec_trigger_stats 的内容都证实了这一点。
SQL Profiler 报告占用空间非常低(3 次读取,0 次写入),但由于我有很多触发器,因此这种情况经常发生,并且最终得到了重要的 total_reads 数字。
关于为什么会发生这种情况的任何提示?有没有办法改变这种行为?