3

我有一个使用 3 个函数和下面几个不同视图的查询,这些视图太复杂,无法在此处发布。我遇到的奇怪的事情是在运行顶级查询时,拥有超过 1 个搜索键会导致查询需要大约一个小时才能运行,而将查询分成两部分每个查询大约需要 5 秒。

这是顶级查询:

Select * 
from  dbo.vwSimpleInvoice i 
inner join dbo.vwRPTInvoiceLineItemDetail d on i.InvoiceID = d.InvoiceID 

当我添加这个 where 子句时:

Where i.InvoiceID = 109581

查询运行大约需要 3 秒。同样,当我添加这个 where 子句时:

Where i.InvoiceID = 109582

大约需要 3 秒。

当我添加这个 where 子句时:

Where i.InvoiceID in (109581, 109582)

大约 50 分钟后,我不得不终止查询,它永远不会返回任何结果。

这发生在运行 SQL Server 2008 R2 Express 的远程客户端服务器上。当我在本地运行它时(也在 SQL Server 2008 R2 Express 上),我没有得到巨大的延迟,最后一个 where 子句需要大约 30 秒才能返回。不过,客户的数据比我多得多。

知道从哪里开始解决这个问题吗?

编辑:

在下面的评论之后,我重建了索引和统计信息,这提高了前两个 where 子句的性能,但对第三个子句没有影响。然后我玩弄了这个查询,发现如果我把它改写为:

Select * 
from  dbo.vwSimpleInvoice i 
inner join  
    (Select * from dbo.vwRPTInvoiceLineItemDetail) d on i.InvoiceID = d.InvoiceID 
Where i.InvoiceID in (109581, 109582)

性能恢复到预期水平,大约 200 毫秒。我现在比以往任何时候都更加困惑正在发生的事情......

编辑2:

其实,我错了。它不是那样重写查询,我在重写期间不小心将 Where 子句更改为:

Where d.InvoiceID in (109581, 109582)

(改为id

仍然有点茫然,为什么这会对内部连接产生如此巨大的影响?


进一步编辑:

玩得更远,我仍然无法理解。

Select InvoiceId from tblInvoice Where CustomerID = 2000

返回:

80442, 4988, 98497, 102483, 102484, 107958, 127063, 168444, 168531, 173382, 173487, 173633, 174013, 174160, 174240, 175389

Select * from dbo.vwRPTInvoiceLineItemDetail
Where InvoiceID in 
(80442, 4988, 98497, 102483, 102484, 107958, 127063, 168444, 168531, 173382, 173487, 173633, 174013, 174160, 174240, 175389)

运行:31 行返回 110 毫秒

Select * from dbo.vwRPTInvoiceLineItemDetail
Where InvoiceID in 
(Select InvoiceId from tblInvoice Where CustomerID = 2000)

运行:31 行返回 65 分钟

4

1 回答 1

3

您遇到的问题(几乎可以肯定)是由于缓存的查询计划造成的,该计划适用于传递给查询的某些版本的参数,但不适用于其他版本(又名Parameter Sniffing)。

这是一种常见的情况,并且经常由于过时的统计数据和/或严重碎片化的索引而变得更糟。

第一步:确保您已重建所有索引,并且非索引列的统计信息是最新的。(另外,请确保您的客户有定期安排的索引维护工作)

exec sp_msforeachtable "DBCC DBREINDEX('?')"
go

exec sp_msforeachtable "UPDATE STATISTICS ? WITH FULLSCAN, COLUMNS"
go

这是规范参考:应用程序慢,SSMS 快?

如果重建索引和更新统计信息后问题仍然存在,那么您有几个选择:

  1. 使用动态 SQL(但请先阅读:动态 SQL 的诅咒和祝福

  2. 利用OPTIMIZE FOR

  3. 利用WITH(RECOMPILE)

于 2012-09-11T03:17:09.063 回答