【问题标题】:SQL Index - are both statements going to do the same?SQL 索引 - 两个语句都会做同样的事情吗?
【发布时间】:2019-06-06 12:37:06
【问题描述】:

我想知道在 SQL Server 中这两条创建非聚集索引的语句是否会有相同的行为?

create nonclustered index EmpLastname_Incl_Firstname 
on employee(lastname) include (firstname);

create nonclustered index EmpLastnameFirstname 
on employee(lastname, firstname)

【问题讨论】:

    标签: sql tsql indexing


    【解决方案1】:

    没有。关键列针对过滤和分组等内容进行了优化,而包含的列针对仅检索列进行了优化。因此,如果您的很多查询如下所示:

    SELECT firstname, lastname
    FROM mytable
    WHERE lastname = 'Doe' AND firstname = 'John'
    

    那么您显示的第二个索引将是首选。如果您只在您的SELECT 中使用lastname,例如以下查询:

    SELECT firstname, lastname
    FROM mytable
    WHERE lastname = 'Doe'
    

    那么第一个查询将是首选。

    如果你有两个查询的混合,你应该只使用第二个索引,因为第二个查询也能够使用第一个索引。

    【讨论】:

    • "then the first index you showed would be preferred" :这是不正确的!您的第一个查询按姓氏和名字过滤,这意味着它需要使用在两列上都完成的索引=意味着首选第二个索引on employee(lastname,firstname)。
    • @RonenAriely 对不起。我的帖子中的查询顺序错误。我会相应地编辑
    • 这很有道理?
    【解决方案2】:

    绝对没有

    INCLUDE 表示列中的数据存储在索引中,但不属于索引排序的一部分

    【讨论】:

      【解决方案3】:

      这些语句不会有相同的行为。包含包含的索引将只允许在姓氏字段上进行键查找,而没有包含的索引将允许在姓氏和名字字段上进行键查找。 Microsoft documentation for indexes with includes。这一点对您的问题特别重要:

      重新设计具有较大索引键大小的非聚集索引,以便只有用于搜索和查找的列是键列。将涵盖查询的所有其他列设为非键列。这样,您将拥有覆盖查询所需的所有列,但索引键本身小而高效。

      如果您需要按名字字段进行搜索,您的索引应将其作为键查找包含在内。

      【讨论】:

        【解决方案4】:

        将列添加到include 将仅将相应的数据存储在 b 树的叶节点级别(而不是树本身)。

        几乎所有可以用include 完成的事情也可以通过将相应的列放在索引的关键部分来完成。例外情况与密钥的长度限制有关。如有疑问,最好将其保留在关键列中。

        话虽如此,将列放在include 中而不是关键部分有一些好处:

        • 生成的索引稍微小(几个百分点)
        • 索引树可能小一级
        • 记录了该索引的列的用途。这使得将来扩展此索引更加容易。

        我发现最后一个是最重要的。

        请查看我最近关于此主题的文章以更好地理解: https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-24
          • 2020-08-05
          • 1970-01-01
          • 1970-01-01
          • 2020-10-28
          • 2021-05-02
          相关资源
          最近更新 更多