我继承了一个非常糟糕的设计和维护数据库,并且一直在使用我对SQL Server的了解和运气保持这个HIGH可用性服务器并且没有完成火灾(之前的开发人员,他们基本上只是保留了系统长达4年)。
今天我遇到了一个非常奇怪的问题。我希望有人可以向我解释一下,如果再次发生这种情况,有办法解决它。
无论如何,存储过程非常简单。它在SHORT日期/时间范围(5分钟范围)之间连接两个表并传回结果(此查询通过Windows服务每5分钟运行一次)。最大的表有100k行,最小的表有10k行。存储过程非常简单,并且确实:
注意:表名和列名已更改,以保护无辜者。
SELECT TOP 100 m.*
FROM dbo.mytable1 m WITH (nolock)
INNER JOIN dbo.mytable2 s WITH (nolock) ON m.Table2ID = s.Table2ID
WHERE m.RowActive = 1
AND s.DateStarted <= DATEADD(minute, -5, getdate())
ORDER BY m.DateStarted
现在,如果我在查询中保留“TOP 100”,查询将一直挂起,直到我停止它(在SMS或存储过程中运行)。如果我删除TOP 100,查询按计划工作并返回50-ash行,就像它应该的那样(如果我们可以帮助它,我们不希望它返回超过100行)。
所以,我做了一些调查,使用sp_who,sp_who2,查看master..sysprocesses并使用DBCC INPUTBUFFER查找可能锁定或阻塞的任何SPID。没有阻止,没有锁定。
今天刚刚开始,这两个表格设计没有变化,而且上次触摸这个查询/表格时我收集的内容是3年前,并且自那以后一直运行没有错误。
现在,附注,我不知道这是否与此有关。但是我在24小时之前对这两个表进行了重新索引,因为它们是99%的碎片(记住,我说这个设计很差,服务器维护得很差)。
任何人都可以解释为什么SQL Server 2008会这样做吗?
答案 0 :(得分:3)
ORDER BY是杀手。它必须读取所有行,按列按顺序排序,然后给出前100行。
答案 1 :(得分:2)
我要做的绝对第一件事就是对完整和前100个查询的查询计划进行并排比较,看看前100名是不是高性能。您可能需要更新统计信息,甚至缺少索引。
答案 2 :(得分:0)
我认为mytable1.DateStarted上没有索引。我认为当您选择SELECT TOP 100时,某些事情可能决定在查询过程中更早地执行排序。