0

我有這個簡單的內部聯接查詢和其執行計劃主表有大約34K記錄和細節表有大約51K記錄。但是這個簡單的查詢建議添加一個索引include(包含我包含在select中的所有主列)。我不期待這可能是什麼原因和補救措施。簡單的內部聯接建議一個包含索引

DECLARE  
     @StartDrInvDate Date ='2017-06-01', 
     @EndDrInvDate Date='2017-08-31' 

    SELECT 
     Mastertbl.DrInvoiceID, 
     Mastertbl.DrInvoiceNo, 
     Mastertbl.DistributorInvNo, 
     PreparedBy, 
     detailtbl.BatchNo, detailtbl.Discount, 
     detailtbl.TradePrice, detailtbl.IssuedUnits, 
     detailtbl.FreeUnits 
    FROM 
     scmDrInvoices Mastertbl 
    INNER JOIN 
     scmDrInvoiceDetails detailtbl ON Mastertbl.DrInvoiceID = detailtbl.DrInvoiceID 
    WHERE 
     (Mastertbl.DrInvDate BETWEEN @StartDrInvDate AND @EndDrInvDate) 

enter image description here

我真正的好奇心就是爲什麼它是在暗示該指數 - 我通常看不到較大的表格

+0

隨着行的數量如果您對目前的表現滿意,您可以放心地忽略這個建議。 – Serg

+0

僅僅因爲SQL Server要求這並不意味着你應該創建它。它基於它在特定查詢上使用的執行計劃的假設。嘗試在Mastertbl.DrInvoiceID上添加非聚集索引幷包含Mastertbl.DrInvDate。查看查詢並播放其上的索引:) – dbajtr

+0

@Serg此查詢實際上是需要一些時間的較大查詢的一部分,並且該查詢在我刪除所有其他連接時提示此索引,並且我只剩下這部分並仍然建議相同的索引 – Zia

回答

1

對於此查詢此行爲:

SELECT m.DrInvoiceID, m.DrInvoiceNo, m.DistributorInvNo, 
     PreparedBy, 
     d.BatchNo, d.Discount, d.TradePrice, d.IssuedUnits, d.FreeUnits 
FROM scmDrInvoices m INNER JOIN 
    scmDrInvoiceDetails d 
    ON m.DrInvoiceID = d.DrInvoiceID 
WHERE m.DrInvDate BETWEEN @StartDrInvDate AND @EndDrInvDate; 

我期望基本指標爲:scmDrInvoices(DrInvDate, DrInvoiceID)scmDrInvoiceDetails(DrInvoiceID)。該索引將允許查詢引擎快速識別與主表中的WHERE相匹配的行,然後查找scmDrInvoiceDetails中的對應值。

其餘列可以包含在任一索引中,以便索引覆蓋查詢。 「封面」意味着所有列都在索引中,因此查詢計劃不需要引用原始數據頁面。

上述策略是SQL Server建議的。

+0

是的,這些索引已經存在 – Zia

1

你也許可以看到它建議索引發票日期的邏輯;它對你想要的行數進行了一些計算,使其超出了它認爲當前存在的行數,並且似乎該列上索引的選擇性使其值得索引。如果你想要55,000中的3行,並且你希望它每5分鐘一次,那麼索引是有意義的。特別是如果該表的增長率意味着明年將有550萬的3排。

包含建議可能更天真地建議將足夠的附加數據與索引值相關聯,這樣可以從索引回答主表所需的整個數據集,而不會觸及表 - 索引基本上是指向行中的行的指針表;當查詢引擎使用索引來查找所需的所有行時,它仍然需要打開表來實際獲取所需的數據。通過在索引中包含數據,您可以刪除需要轉到表中的表單,並且它有時是合理的,但不是其他表單(爲創建許多索引,實質上覆制大部分/全部表數據以便很少運行查詢是浪費磁盤空間)。

也要考慮到,現在在調試工具中運行此查詢的頻率正在影響SQLServer對查詢使用頻率的看法。我經常發現我的SQLAzure門戶提供索引建議,這要感謝開發者反覆運行查詢,調試它,當我真正知道在prod中,該查詢將每月使用一次,因此我放棄了建立索引的建議包括大多數表格,當直接「索引只搜索列」將做的很好,不包括必要的

因此,這些建議不應該盲目地被注意,因爲SQLServer無法知道你打算使用這個或類似的查詢在現實世界中的應用。索引創建和維護應該小心謹慎地進行;例如它可能是這個查詢要求這個索引,另一個查詢會希望在另一個列上有一個索引,但是在兩個列上創建一個索引(按特定順序),然​​後在任何查詢搜索在索引爲第二的列中,包括一個謂詞,無論查詢是否需要,它都會觸及第一個索引列

例如,在您的發票表中,您有一列指示其是否已付費以及您的其他位置應用程序中有另一個查詢可以計算未付發票的數量。即使狀態謂詞是冗餘的,您也可以有兩個索引 - 一個在發票日期(對於此查詢)和一個對狀態(對於該查詢)或兩個列(狀態,日期)和該查詢中的一個具有WHERE status = 'unpaid' AND date between...的謂詞。爲什麼它可能是多餘的?假設你知道你只會從上週選擇尚未發出的發票,所以只能是未付款的。這就是我的意思,「對索引進行深思熟慮」 - 你知道很多有關你的應用的信息SQLServer永遠無法解決問題。通過在「從上週獲取發票」查詢中包含冗餘狀態列(即使狀態在邏輯上是冗餘的),您允許查詢引擎使用首先按狀態排序的索引,然後按日期排序。這意味着你可以擺脫不得不只維持一個指標,並且它可以通過兩個查詢

索引維護和創造的邏輯中可以是全職工作..;)