覆盖索引并摆脱Key Lookup

时间:2015-06-11 22:15:45

标签: sql-server indexing key

我有一个SQL语句,它给我一个关键查找,以便在下面处理这个查询。由于它是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'

我尝试为此设置覆盖索引,因为它在异常表的主键上对Clustered索引进行了键查找。

ExceptionId

这是我选择的列上的覆盖索引,其中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%。

Processing Plan

任何见解都会很棒

3 个答案:

答案 0 :(得分:0)

您正在获取一行,并且您正在尝试优化查询。 61%(此查询的几乎所有工作都已完成)与查询的整个查询计划相关。你可以推动多少是有限制的。 - SQL Server引擎只投入尽可能多的工作(优化查询),因为它认为值得,并且它将您的查询视为不值得花费大量精力的东西。

答案 1 :(得分:0)

问题是你的索引真的不能用于连接。为了可以使用,索引中的第一个字段必须是这样的,你还要加入表(或存在于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 :(得分:0)

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

相关问题