【问题标题】:What is the Difference between these two indexes in SQL Server?SQL Server 中这两个索引有什么区别?
【发布时间】:2012-12-04 22:05:25
【问题描述】:

我根据索引向导针对不同场景的建议创建了这两个索引。 我想知道它们是相同的还是不同的?

索引(1):

CREATE NONClustered Index [IX_Rec_RecoveryDate_RecoveryDateTypeKey_CaseId] 
ON [Rec].[RecoveryDate] ([RecoveryDateTypeKey], [CurrentFlag])
INCLUDE (CaseId)

索引(2):

CREATE NONClustered Index [IX_Rec_RecoveryDate_currentFlag] 
ON [Rec].[RecoveryDate] ([CurrentFlag])
INCLUDE (CaseId, RecoveryDateTypekey)

【问题讨论】:

    标签: sql-server sql-server-2008 tsql indexing


    【解决方案1】:

    问题是,您要优化哪些查询?

    这两个索引非常不同。第一个索引非常适合这样的查询:

    SELECT CaseId 
    FROM Rec.RecoveryDate
    WHERE RecoveryTypeKey = 5
    AND CurrentFlag = 1 -- or whatever
    

    第一个索引 WHERE 子句中的列。 SQL Server 将能够搜索指定的 RecoveryDateTypeKey 和 CurrentFlag。由于 CaseId 已包含在索引叶节点中,因此 SQL Server 不必重新加入表即可获取它。

    使用相同的查询,第二个索引的行为会有所不同。如果幸运的话,SQL Server 会搜索 CurrentFlag 为 1 的所有记录。然后,它会遍历这些叶节点,寻找匹配的 RecoveryTypeKey。另一方面,如果有很多 CurrentFlag 为 1 的记录,SQL Server 可能会选择执行索引扫描。

    再一次,如果你想优化这样的查询:

    SELECT CaseId, RecoveryTypeKey
    FROM Rec.RecoveryDate
    WHERE CurrentFlag = 1
    

    第一个索引没有用,因为 CurrentFlag 是索引中的第二列。 SQL Server 无法搜索 CurrentFlag = 1,因此它可能会进行索引扫描。

    【讨论】:

      【解决方案2】:

      它们是不同的。索引 1 索引两列,索引 2 索引一列但在节点中包含两列。

      区别基本上意味着如果您使用两列进行搜索,索引 1 可能比索引 2 快得多。
      索引 2 会比一列的普通索引更好,因为如果您需要结果中的另一列,索引 2 已经具有该值,因此不需要查找实际表。

      【讨论】:

        【解决方案3】:

        索引存储相同的信息(Recovery 表中每行 1 行,列 caseid、RecoveryDateTypeKey、CurrentFlag),但以不同的顺序组织,因此可用于不同的查询。

        第一个索引可以处理where子句如

        WHERE RecoveryDateTypeKey = @p1 --Prefix matching!
        

        和

        WHERE RecoveryDateTypeKey = @p1 AND CurrentFlag = @p2
        

        第二个索引只处理

        WHERE CurrentFlag = @p2
        

        如果 CurrentFlag 是低基数列,例如 bit 或 char(1) (Y/N),那么我建议使用过滤索引。

        CREATE INDEX IX_REC_Yes_fltr on Recovery (RecoveryDateTypeKey) WHERE (CurrentFlag = 'Y')
        INCLUDE (CaseId) --Assumes that CurrentFlag = 'Y' is the most used value
        
        --Maybe even a second one.
        CREATE INDEX IX_REC_No_fltr on Recovery (RecoveryDateTypeKey) WHERE (CurrentFlag = 'N')
        INCLUDE (CaseId) --Maybe handle CurrentFlag = 'N' as well.
        

        每个过滤后的索引只包含符合条件的值,因此组合起来它们的大小与未过滤的索引相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-08-05
          • 2012-08-05
          • 2020-02-02
          • 2022-01-02
          • 2012-04-19
          • 1970-01-01
          相关资源
          最近更新 更多