【问题标题】:Covering index and getting rid of Key Lookup覆盖索引并摆脱 Key Lookup
【发布时间】:2015-06-11 22:15:44
【问题描述】:

我有一个 SQL 语句,它给了我一个 Key Lookup 来处理下面这个查询。由于它是 3 部分联合的一部分,因此最好摆脱键查找。

我的查询如下。

SELECT
   c.customerName,
   c.customerNumber,
   totals.TotalLoanAmount,
   totals.TotalCommitmentAmount,
   l.loanNumber,
   l.commitmentAmount,
   ed.amountThreshold,
   ex.exceptionId,
   IsNull(ex.reminderDateGracePeriod, ed.defaultReminderDateGracePeriod) AS gracePeriod,
   ex.reminderDate AS targetDate,
   IsNull(ex.exceptionState, 'N') AS exceptionState,
   ex.exceptionState AS GeneralExceptionState
FROM 
   exceptionDefinition AS ed 
INNER JOIN 
   exception AS ex ON ed.exceptionDefId = ex.exceptionDefId
                   AND ex.loanId IS NULL
INNER JOIN 
   customer AS c ON c.customerId = ex.customerId
LEFT OUTER JOIN 
   loan AS l ON l.loanId = ex.loanId
INNER JOIN 
   viewCustomerLoanTotals AS totals ON totals.customerId = c.customerId
WHERE 
   ed.requireReminderDate = 'Y'
   AND ex.statusType = 'required'

我试图为此设置一个覆盖索引,因为它在异常表的主键上对聚集索引进行键查找。

异常标识

这是我选择的列的覆盖索引,其中 statusType 作为 where 子句的一部分。

CREATE NONCLUSTERED INDEX [IX_EXCEPTIONPROCESS_COVER] ON [dbo].[exception]
(
    [exceptionId] ASC,
    [loanId] ASC,
    [reminderDate] ASC,
    [reminderDateGracePeriod] ASC,
    [exceptionState] ASC
)
INCLUDE ([statusType]) ON [PRIMARY]

这根本不会对 Key 查找产生任何影响。我试图强迫它使用索引,但它变成了 91% 的资源,而不是我试图摆脱的 61%。

任何见解都会很棒

【问题讨论】:

    标签: sql-server indexing key


    【解决方案1】:

    问题是您的索引不能真正用于连接。为了可用,索引中的第一个字段必须是这样的,您也可以将表加入(或存在于 where 子句中)。

    INNER JOIN exception AS ex ON 
        ed.exceptionDefId = ex.exceptionDefId AND 
        ex.loanId IS NULL
    

    您正在使用 exceptionDefId (+loanID) 加入表,但索引没有:

    CREATE NONCLUSTERED INDEX [IX_EXCEPTIONPROCESS_COVER] ON [dbo].[exception]
    (
        [exceptionId] ASC,
        [loanId] ASC,
    ...
    

    如果这个索引只针对这个 SQL,那么应该会更好:

    CREATE NONCLUSTERED INDEX [IX_EXCEPTIONPROCESS_COVER] ON [dbo].[exception] (
        exceptionDefId,
        loanId,
        statusType
    ) include (
       exceptionId,
       reminderDateGracePeriod,
       reminderDate,
       exceptionState,
       customerId
    )
    

    索引中字段的顺序也应基于选择性(=每个键的平均行数最少)。对于包含无关紧要的字段。

    【讨论】:

    • 非常感谢。这工作得很好。非常感谢您提供的索引见解。
    【解决方案2】:

    您得到一行,并且您正在尝试优化查询。 61%(该查询的几乎所有工作都在此完成)是相对于查询的整个查询计划而言的。你可以推多少是有限制的。 - SQL Server 引擎只投入它认为值得的工作(优化查询),并将您的查询视为不值得投入大量精力的事情。

    【讨论】:

      【解决方案3】:

      您的“覆盖”索引不包括根据“输出列表”从该表中使用的所有列。添加剩余的列。

      【讨论】:

        猜你喜欢
        • 2016-03-21
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多