2016-07-12 84 views
0

我有一个执行计划,显示大部分成本都在一个KeyLookup内。虽然我知道keylookups是什么,并且在一个简单的SQL语句中,我可以选择它们,但我更加努力的是如何从实际执行计划输出中准确读出要创建的索引。从SQL Server执行计划分析keylookup

在我的例子,我有下面的执行计划:

enter image description here

我不能确定应该是我的新的覆盖索引中的哪些列(如果我确实需要一个),以及什么样的顺序,他们应该也在。我尝试了一个简单的非聚集索引Id, OccurenceDate, IsFinal,但在重新运行(大)查询时,我仍然可以看到keylookup显示,这可能是正常的,因为查询优化器比我聪明,聚集索引更好。但我不确定看到执行计划到底发生了什么。

注意。重新运行我的查询时。我用清理

DBCC FREEPROCCACHE WITH NO_INFOMSGS; 

编辑查询计划缓存:增加所产生下面的执行计划的存储过程的相关部分。

SELECT 
    ro.Id, ro.OccurrenceDate, ro.RentId, 
    'Final Rent Due', p.Id, l.Id, 0, 
    p.Title, 8, 
    @false AS IsComplete, @true AS IsOverdue, 
    @false AS IsAdvanceNotification, 0 AS TodayToDo, 
    null As EndDate 
FROM 
    RentOccurrences ro 
INNER JOIN 
    Rents r ON ro.RentId = r.Id 
INNER JOIN 
    Leases l ON r.LeaseId = l.Id 
LEFT OUTER JOIN 
    Invoices i ON i.rentId = r.Id AND i.IsActive = 1 
       AND ro.OccurrenceDate = i.DueDate 
INNER JOIN 
    Properties p ON l.PropertyId = p.Id 
INNER JOIN 
    @Temp_Table_CustomerIds c ON c.Id = p.CustomerId 
WHERE 
    (p.PropertyManagerId = @CurrentUserId OR 
    r.DelegatedUserId = @CurrentUserId) 
    AND r.IsActive = 'True' 
    AND l.IsActive = 'True' 
    AND p.IsActive = 'True' 
    AND ro.IsFinal = 'True' 
    AND @ShowFinalRents = 1 
    AND i.Status = 2 
    AND i.AmountDue > 0 
    AND ro.OccurrenceDate < @TodaysDate 
+1

请编辑您的问题并包括查询。 –

+0

群集键查找实际上很慢吗?我无法想象覆盖指数会提高速度,因为两者都会包含所需的数据。 –

+0

@GordonLinoff。我可以包含查询(这是一个巨大的存储过程,因此可能需要将其分解到这里),但我的主要问题是如何读取执行计划细分,因为它涉及到keylookups。我在这里看什么?仅基于执行计划,我能够就如何创建索引做出决定? – MindingData

回答

0

如果查询运行频繁,真正下跌的性能比你可能需要一个指数on RentOccurence (OccurrenceDate asc,isFinal asc) include (pk_col)on RentOccurence (OccurrenceDate asc) include (pk_col, isFinal)。哪一个更好取决于统计数据。您可以使用以下查询检查索引统计与建议使用以下查询

SELECT 
    migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 
    'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) 
    + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']' 
    + ' ON ' + mid.statement 
    + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
    + ISNULL (mid.inequality_columns, '') 
    + ')' 
    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, 
    migs.*, mid.database_id, mid.[object_id] 
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 
WHERE migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) > 10 
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC