昨天和今天,我花了几个小时试图排除一个特定的数据库查询为什么需要很长时间(3+分钟)才能在我在本地实例上还原的数据库上执行,而在生产服务器上只需要一小部分时间。(这不仅仅是生产服务器具有更高的规范的问题,因为以前对我的本地实例执行了相同的查询。)
我要试着用最好的方法来解释这个问题--意味着这篇文章可能有点长。这个查询非常直截了当:
SELECT [t0].[BillId], [t0].[CustomerId], [t0].[BillDate], [t0].[DueDate],
[t0].[Period], [t0].[Total], [t0].[Balance], [t0].[DateCreated], [t0].[DateModified] --, other fields
FROM [dbo].[Bills] AS [t0]
WHERE ([t0].[Period] = 201307) AND (([t0].[DateModified] >= '2013-07-04 17:00:00.000')
OR (([t0].[DateModified] < '2013-07-04 17:00:00.000') AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[BillDetails] AS [t1]
WHERE [t1].[BillID] = [t0].[BillID] AND [t1].[DateModified] >= '2013-07-04 17:00:00.000'
))))
上面的查询返回与某个时间段相关联并自特定时间点以来已被修改的账单。如果票据的DateModified字段中的值晚于指定日期,或者相关子行(BillDetails
)中的DateModified字段上的值晚于指定日期,则视为修改。我将在引用上述查询返回的结果时使用"delta“一词。
这有点奇怪,但在我的本地实例中,这个查询的执行似乎有点阻塞,特别是当没有增量时,即自上次指定的日期以来Bills
和BillDetails
没有发生任何更改时。当需要返回增量时,查询只需一秒钟。在活动/生产数据库上,查询对这两种场景的响应都非常快。
我以前曾遇到过这个问题,但我没有记录我是如何解决的--很可能是因为我无法从我尝试过的许多事情中找出解决它的方法。在此期间,“阻塞”发生在生产数据库上,而我的本地实例却很好。我怀疑这和指数有关。
当它现在在我的本地实例上递归时,索引是主要的怀疑。我运行了我的实用程序脚本,用于重新组织平均碎片在5%到30 %之间的索引,以及重建平均碎片超过30 %的索引。这似乎没能解决问题。从那以后,我尝试了很多事情,但是修复它的方法是删除和重新创建Bills
表上的非聚集索引。
我在Bills
表上定义了三个非聚集索引,定义如下(或多或少):
NCI_IDX1 ([CustomerId] ASC)
NCI_IDX2 ([CustomerId] ASC, [Period] ASC, [BillId] ASC)
NCI_IDX3_Inc_Various ([Period] ASC, [DateModified] ASC, [BillId] ASC, [CustomerId] ASC) INCLUDE ([BillDate], [Total], [Balance] /* more fields */)
根据我的经验,当我试图解决这个问题时,我有几个问题困扰着我的头脑。
Q:重建索引是做什么的?它是否等同于手动删除和重新创建索引?
Q:将索引结果删除到与被删除的索引相关的统计数据中。索引的重建是否“刷新”或“重置”相关统计信息?
Q:考虑到查询优化器在选择执行计划时对统计信息的依赖,统计数据会对查询执行的阻塞负责吗?
Q:根据MSDN,不能使用DROP STATISTICS
删除索引的统计信息。这是否意味着必须删除和重新创建索引才能重置统计信息?
注意: LINQ和C#是标记的,因为上面查询的来源是数据层中使用LINQtoSQL的C#应用程序。
发布于 2013-07-11 01:58:19
我发现这句话:
但是,索引重新组织根本不更新统计信息,因为整个表不是一次性分析的(只有具有碎片的页面才会被重新组织)。
在本文中:http://www.sqlskills.com/blogs/kimberly/the-accidental-dba-day-15-of-30-statistics-maintenance/
也许您的重构/重新组织索引的脚本只是重新组织了索引,但是没有重新构建 it (由于碎片较低),因此该索引上的统计数据变得“陈旧”。
这篇文章有一个很好的建议:
因此,如果您发现您的索引维护脚本正在定期地重新组织索引,那么您需要确保您也添加了统计维护。
https://stackoverflow.com/questions/17483945
复制