背景
我有一个针对SQL Server 2008 R2的查询,该查询联接和/或左联接约12个不同的“表”。该数据库相当大,有许多表超过5000万行和大约300个不同的表。适用于在全国设有10个仓库的大型公司。所有仓库都读取和写入数据库。所以它很大而且很忙。
我遇到的查询看起来像这样:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
请注意,联接之一是在不相关的子查询上。
问题是从今天早上开始,在没有对系统进行任何更改(我或我的团队中的任何人都知道)的情况下,该查询通常需要运行2分钟左右,而开始需要花一个半小时才能运行-跑了。数据库的其余部分运行正常。我已经从通常运行该程序的过程中取出了此查询,并以相同的慢度在带有硬编码参数变量的SSMS中运行了该查询。
奇怪的是,当我使用不相关的子查询并将其放入临时表中,然后使用该子查询代替子查询时,查询运行良好。另外(这对我来说是最奇怪的),如果我将这段代码添加到查询的末尾,则查询运行良好:
and t.name like '%'
我从这些小实验得出的结论(可能是错误的)是,放慢速度的原因是由于如何设置SQL的缓存执行计划-当查询略有不同时,它必须创建一个新的执行计划。
我的问题是这样的:当以前运行快速的查询突然在深夜开始运行,并且除此查询外没有其他影响,我该如何解决它以及如何避免将来发生?我怎么知道SQL在内部做的事情使其变得如此缓慢(如果运行了错误的查询,我可以得到它的执行计划,但它不会运行-也许预期的执行计划会给我一些东西?)?如果此问题与执行计划有关,那么如何避免SQL认为真正糟糕的执行计划是个好主意?
同样,这也不是参数嗅探的问题。我以前见过这种情况,不是这样,因为即使我在SSMS中对变量进行硬编码,性能仍然很慢。