【问题标题】:Difference between 2 indexes with columns defined in reverse order以相反顺序定义列的 2 个索引之间的差异
【发布时间】:2010-12-05 17:03:48
【问题描述】:

以下两个索引有区别吗?

  • IDX_IndexTables_1
  • IDX_IndexTables_2

如果有,有什么区别?

create table IndexTables (
    id int identity(1, 1) primary key,
    val1 nvarchar(100),
    val2 nvarchar(100),
)

create index IDX_IndexTables_1 on IndexTables (val1, val2)
GO

create index IDX_IndexTables_2 on IndexTables (val2, val1)
GO

【问题讨论】:

    标签: sql sql-server tsql indexing composite-index


    【解决方案1】:

    是的。有区别。

    复合索引IDX_IndexTables_1 可用于在where 子句中使用val1 列的任何查询。

    复合索引IDX_IndexTables_2 可用于在where 子句中使用val2 列的任何查询。

    因此,例如IDX_IndexTables_2 不能用于此查询(但可以使用 IDX_IndexTables_1):

    SELECT val1, val2 FROM IndexTables
    WHERE val1 = some_value
    

    但可用于此查询:

    SELECT val1, val2 FROM IndexTables
    WHERE val2 = some_value AND val1 = some_other-value
    

    考虑复合索引的方法是考虑纸质电话簿;它由 surname 列索引,然后是 firstname 列:您可以按 surname 查找,但不能单独按 firstname。

    【讨论】:

    • 您对综合指数的类比确实帮助我很容易理解其中的区别。谢谢,米奇。
    【解决方案2】:

    你所拥有的是一个复合索引。当您的 WHERE 子句未使用复合索引中的所有列时,顺序很重要。

    考虑这个查询:

    SELECT val1
    FROM IndexTables
    WHERE val1 = 'MyValue'
    

    为了知道什么索引可能被认为是从左到右读取复合索引中的列。如果在您读取查询中的所有列之前查询中不存在该列,则不会使用索引。

    IDX_IndexTables_1(val1, val2):从左到右读取 val1 存在,它是我们唯一的列,所以会考虑这个索引

    IDX_IndexTables_2(val2, val1):从左到右读取 val2 在此查询中不存在,因此不会使用。

    【讨论】:

      【解决方案3】:

      多列索引在概念上与获取所有列字段并将它们连接在一起没有什么不同——将结果索引为单个字段。

      由于索引是 b 树,它们总是从左到右搜索。您必须从左侧开始搜索以配对结果,然后向右移动索引才能完成其工作并提供有用的结果。

      只有一个字段被索引:

      WHERE val1 LIKE 'myvalue%' (uses index)
      WHERE val1 LIKE '%myvalue' (cannot use index)
      

      同样的概念也适用于多列索引:

      当order为val1,val2时

      WHERE val1='value1' (uses index)
      WHERE val2='value2' (cannot use index)
      

      当order为val2,val1时

      WHERE val1='value1' (cannot use index)
      WHERE val2='value2' (uses index)
      

      如果两个字段都完全匹配,则索引顺序在这种情况下无关紧要。

      WHERE val1='value1' AND val2='value2' (uses index in any order)
      

      【讨论】:

        【解决方案4】:

        前面的答案描述了如何使用每个索引的第一列。 (在 where 子句中)。

        我认为指出第二列很有用也很重要,因为它可能会提高涉及第二列的查询的性能。

        以下查询将在 IDX_1 上完成索引查找,将有价值的查找保存到基表(因为 val2 已经是索引的一部分)。

        SELECT val2 from IndexTables where val1 = @someVal1
        

        同样,反向索引会优化这个查询:

        SELECT val1 from IndexTables where val2 = @someVal2
        

        但是,两个索引中只需要一个(无关紧要)来优化以下查询:

        SELECT val1, val2 from IndexTables where val1 = @someVal1 and val2 = @someVal2
        

        这表明,根据您的表收到的查询,可能有合理的理由同时拥有两个索引。

        【讨论】:

        • 请注意,如果索引不是唯一的,则一个组合可能比另一个组合更具选择性,具体取决于分布。但这可能是微优化...
        • 好点迈克。在更大的范围内,这可能根本不是“微观”优化。
        【解决方案5】:

        其他人已经回答说他们是不同的,我同意。

        不过我会补充一些其他的想法......

        • (col1, col2) 索引意味着您不需要单独在 col1 上建立索引
        • (col2, col1) 索引意味着您不需要单独在 col2 上建立索引
        • 如果覆盖,则顺序很重要(例如,在 col1 上的 WHERE,SELECT col2)
        • 方向 (ASC/DESC) 也很重要 (Other question 1, Other question 2)

        【讨论】:

        • 如果你有 (col1, col2),那是不是意味着你可以只拥有 (col2) 而不是 (col2, col1)?
        • @Renae:也许吧,但这是举例。
        猜你喜欢
        • 1970-01-01
        • 2020-08-06
        • 2019-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多