2016-07-12 120 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