【问题标题】:Why am I getting a Clustered Index Scan when the column is indexed?当列被索引时,为什么我会得到聚集索引扫描?
【发布时间】:2012-09-25 15:07:40
【问题描述】:

所以,我们有一个表InventoryListItems,它有几列。因为我们有时会根据特定列(g_list_id,一个外键)来查找行,所以我们将该外键列放置在一个非聚集索引中,我们称之为MYINDEX

所以当我搜索这样的数据时:

-- fake data for example
DECLARE @ListId uniqueidentifier
SELECT @ListId = '7BCD0E9F-28D9-4F40-BD67-803005179B04' 

SELECT *
FROM [dbo].[InventoryListItems]
WHERE [g_list_id] = @ListId

我希望它会使用MYINDEX 索引来查找所需的行,然后在这些行中查找信息。所以不如在索引本身中找到我们需要的所有内容,但仍然比对表进行全面扫描要好。

但我似乎仍在进行聚集索引扫描。我不知道为什么会这样。

如果我只选择索引包含的列中的值,它会执行我期望的操作,即索引搜索,并且只是从索引中提取所有内容。

但是如果我SELECT *,为什么它只是放弃索引并进行扫描,因为它在 WHERE 子句中被引用,似乎仍然可以从使用它中受益匪浅?

【问题讨论】:

  • 这些链接将有助于回答您的问题:Link1Link2Link3希望这会有所帮助。

标签: sql-server-2005 indexing


【解决方案1】:

由于您正在执行SELECT * 并因此检索所有列,SQL Server 的查询优化器可能已经决定只进行聚集索引扫描更容易和更有效 - 因为它需要无论如何都要转到聚集索引叶级别以获取所有列(并且首先进行查找,然后进行键查找以实际获取整个数据页,这是一项非常昂贵的操作 - 在此设置中扫描可能更有效)。

我几乎可以肯定你是否尝试

SELECT g_list_id
FROM [dbo].[InventoryListItems]
WHERE [g_list_id] = @ListId

然后会有一个索引 seek 代替(因为您只检索单个列 - 不是所有内容)。

这就是为什么我建议在使用 SELECT * .... 时要格外小心的原因之一 - 尽可能避免使用它。

【讨论】:

  • 理论上,它应该进行搜索和键查找,但这完全取决于表的宽度,g_list_id 是主键还是唯一键,可能还有许多其他因素我不够清醒,无法抓住。
  • @AaronBertrand: true,如果 g_list_id 只返回一个(或非常少)行 - 但如果这匹配 10、20、50 行...... .那么做所有这些关键查找将太昂贵了 - 对吧?
  • @marc_s 是的,这是真的。我在倒数第二段强调了这一点……但我想我不明白为什么。如果表中有数百万行,而我们选择了 1,这还会发生吗,或者这是优化器可能会选择的东西,并决定另一种方式?
  • @Beska:如果选择性足够高(例如,您从大型数据集中选择 足够多 行),那么可能会进行五次搜索和五次键查找再便宜一点。您无法真正分辨 - 查询优化器使用统计信息进行此调用。这也是这些统计数据如此重要且需要始终保持最新的原因!
  • @marc_s 是的,这就是我想说的“主键或唯一” - 你是对的,如果它匹配多行,可能会有一个临界点+查找比扫描更昂贵。但是,不知道临界点在哪里。
猜你喜欢
  • 2015-01-27
  • 2013-11-28
  • 2014-12-18
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
相关资源
最近更新 更多