【问题标题】:What goes wrong when I add the Where clause?添加 Where 子句时出了什么问题?
【发布时间】:2015-01-13 12:57:47
【问题描述】:

我有一个简单的查询:

 Select Distinct BOLTYPENAME, BOLTYPE.BOLTYPE From BOLTYPE
 Inner Join WORKORDER on WORKORDER.BOLTYPE=BOLTYPE.BOLTYPE
 Inner Join BOLMAIN On BOLMAIN.BOLID=WORKORDER.BOLID 
 Where BOLMAIN.CORID=156

当我在没有“Where”子句的情况下运行此查询时,需要 0.1 秒。但是添加 where 子句会导致它需要 1 分钟才能返回。所有的表都有相关的索引并且它们已经被去碎片化。三张表的行数为:

BOLTYPE:11 行

BOLMAIN:71,455 行

WORKORDER:197,500 行

以下是执行计划:

没有 Where 子句(0.1 秒):

使用 Where 子句(60 秒):

知道可能是什么问题吗?

更新:以下是相关的索引定义:

CREATE NONCLUSTERED INDEX [BOLIDX] ON [dbo].[WORKORDER]
([BOLID] ASC)
GO

CREATE NONCLUSTERED INDEX [CORIDX] ON [dbo].[BOLMAIN]
([CORID] ASC)
INCLUDE ([BOLID])
GO

CREATE NONCLUSTERED INDEX [BOLTYPEIDX] ON [dbo].[WORKORDER]
([BOLTYPE] ASC)
GO

【问题讨论】:

  • 这也需要同样的时间吗?选择 Distinct BOLTYPENAME, BOLTYPE.BOLTYPE From BOLTYPE, WORKORDER, BOLMAIN where WORKORDER.BOLTYPE=BOLTYPE.BOLTYPE AND BOLMAIN.BOLID=WORKORDER.BOLID AND BOLMAIN.CORID=156
  • 是的。需要同样的时间。
  • 您的索引看起来不正确。你能用他们的定义来编辑吗?
  • 请粘贴创建表脚本
  • 添加表脚本会太长,因为有几十个其他表和互连外键。我已经发布了相关的索引定义。

标签: sql-server indexing


【解决方案1】:

重新创建 CORIDX 索引,使其覆盖 BOLID。您正在加入 BOLID,因此您希望它成为索引的一部分,而不仅仅是包含的列之一。

换句话说:

CREATE NONCLUSTERED INDEX [CORIDX] ON [dbo].[BOLMAIN]
([CORID] ASC, [BOLID] ASC)

【讨论】:

  • 或者只创建两个单独的索引。多列索引似乎不太适合。
  • 他已经有了两个独立的索引。当没有 WHERE 子句时,优化器使用 PK_BOLMAIN,我打赌它在 BOLID 上。所以他在 BOLID 上有 PK_BOLMAIN,在 CORID 上有 CORIDX。我认为多列索引将消除表假脱机并加快嵌套循环。
  • 太棒了!!!那解决了!我不知道将列移动到索引的一部分而不是仅仅将其包含在索引中会产生如此大的不同!非常感谢!
  • @navigator 仅包含一列意味着您不需要对您选择的值进行表查找(除非索引已将结果过滤到可管理的行数)。它不会提高 按该列过滤 的性能。基本上,您通常希望将 include 用于要选择这些列的大表,同时由其他人过滤 - 选择是 included,而 wheres 是索引本身的一部分。哦,包括主列根本没有帮助 - 索引应该已经有主列。那么BOLID是不是PK?
  • @Luaan,谢谢,非常感谢。但这也是让我困惑的地方。 BOLID 是 BOLMain 表的主标识键。那么为什么我们需要将它添加到另一个索引中呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多