【问题标题】:Index Not Used When Field Selected选择字段时不使用索引
【发布时间】:2018-08-31 18:53:47
【问题描述】:

我遇到了一种奇怪的情况,在我的选择列表中包含一个值决定了我的索引是否用于查找。

我在 cTable(cf1,cf2,cf3) 上创建了一个索引。

在第一种情况下,对 cTable 执行表扫描:

select
    a.bkey
    ,c.mappedvalue
from
    aTable a
    LEFT JOIN bTable b
       ON b.bkey = a.bkey
    LEFT JOIN cTable c ON (
        c.[cf1] = b.[cf1] and
        c.[cf2] = b.[cf2] and
        c.[cf3] = a.[cf3]
    )
;

但是,当我从选择列表中删除 mappedvalue 列时,会使用索引:

select
    a.bkey
    --,c.mappedvalue
from
    aTable a
    LEFT JOIN bTable b
       ON b.bkey = a.bkey
    LEFT JOIN cTable c ON (
        c.[cf1] = b.[cf1] and
        c.[cf2] = b.[cf2] and
        c.[cf3] = a.[cf3]
    )
;

有人遇到过这个吗?优化器只是决定避免索引吗?

【问题讨论】:

  • 对于你的最后一个问题,是的,它选择忽略它。 a 和 b 表的索引是什么?
  • 截至目前,ab 在对应的 c 字段上没有索引。我对此感到疑惑,但a 是一个巨大的表,所以在请求索引之前我需要确定。
  • 投了赞成票,不是因为这个问题,而是因为开始并参与了一次好的学习对话。
  • 提示:对于数据库性能问题,包含实际执行计划会很有帮助。一个方便的工具是Paste The Plan

标签: sql-server tsql indexing


【解决方案1】:

当您删除列时,您的索引为covering index

select
    a.bkey
    --,c.mappedvalue
from
    aTable a
    LEFT JOIN bTable b
       ON b.bkey = a.bkey
    LEFT JOIN cTable c ON (
        c.[cf1] = b.[cf1] and
        c.[cf2] = b.[cf2] and
        c.[cf3] = a.[cf3]
    )
;

你可以加INCLUDE:

 CREATE INDEX idx ON cTable(cf1,cf2,cf3) INCLUDE (mappedvalue);

然后查询:

select
    a.bkey
    ,c.mappedvalue
from
    aTable a
    LEFT JOIN bTable b
       ON b.bkey = a.bkey
    LEFT JOIN cTable c ON (
        c.[cf1] = b.[cf1] and
        c.[cf2] = b.[cf2] and
        c.[cf3] = a.[cf3]
    )
;

应该使用索引idx

【讨论】:

  • 这对我来说没有意义。那么对于任何具有单个主键列的常规表,如果您从该表中选择主键以外的任何内容,索引将被忽略?
  • @Jaime 不,不是那个意思。它将使用索引进行快速行定位,然后使用键查找(使用嵌套循环)来获取不在索引中的其他列。在您的情况下,查询优化器可能会计算出直接从表中读取比在索引中更容易(您没有任何类型的 WHERE 子句),并且可能基于基数,它将返回整个表的 20% 以上。
  • 当您拥有SELECT * FROM tab WHERE pk_col = ? 时,它将在 pk_col 和 key_lookup 的其余列上使用索引查找。当您拥有SELECT * FROM tab 时,没有必要先读取索引然后再读取表格,因为您可以直接读取表格。
  • 好的。我开始明白了。大多数c 表可能会在查询中返回,尽管它在某种程度上受到ab 的内容的限制。如果我对b 添加了一个限制,这反过来又将映射值的数量限制在~5%,那么它可能会使用索引吗?他们上面的查询实际上是用作视图,因此稍后会发生限制。
  • 仍然取决于。即使它是查看 SELECT * FROM (your_view_that_wraps_query) WHERE ... 取决于 where 条件以及查询优化器是否决定执行 predicate pushdown
猜你喜欢
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
相关资源
最近更新 更多