我昨天和今天花了几个小时试图解决为什么一个特定的数据库查询正在采取长(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
。当有delta返回时,查询将花费几分之一秒。在生活/生产数据库上,对于这两种情况,查询响应都非常快。
我也碰到过这个问题之前一次,但我没有记录我是如何解决它 - 最有可能是因为我无法弄清楚什么固定它的很多东西我试过了。在那段时间,生产数据库上发生了“阻塞”,而我的本地实例很好。我怀疑这与索引有关。
当现在复发了我的本地实例的指标为主要嫌疑人。我运行了我用于重新组织索引的实用程序脚本,其平均碎片率在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
下降。这是否意味着必须删除并重新创建索引才能重置统计信息?
注意:因为上述查询的来源是在数据层中使用LINQtoSQL的C#应用程序,所以LINQ和C#被标记。