2015-10-06 123 views
2

我有以下的sql。當我檢查這個查詢的執行計劃時,我們會觀察索引掃描。我如何用索引查找來替換它。我在IdDeleted列上有非聚集索引。 Execution Plan性能調整SQL

SELECT Cast(Format(Sum(COALESCE(InstalledSubtotal, 0)), 'F') AS MONEY) AS TotalSoldNet, 
     BP.BoundProjectId            AS ProjectId 
FROM BoundProducts BP 
WHERE BP.IsDeleted=0 or BP.IsDeleted is null 
GROUP BY BP.BoundProjectId 

我試過這樣並得到索引查找,但結果是錯誤的。

SELECT Cast(Format(Sum(COALESCE(InstalledSubtotal, 0)), 'F') AS MONEY) AS TotalSoldNet, 
     BP.BoundProjectId            AS ProjectId 
FROM BoundProducts BP 
WHERE BP.IsDeleted=0 
GROUP BY BP.BoundProjectId 

任何人都可以好心地建議我使用索引查找來獲得正確的結果集。

我的意思是如何替換(BP.IsDeleted = 0或BP.IsDeleted爲null)條件以利用索引查找。

編輯,添加的行數從其中一個答案的評論:

null: 254962 rows 
0: 392002 rows 
1:  50211 rows 
+0

我的索引定義有兩列(BoundProjectId,IsDeleted)。我想將其更改爲索引搜索而不是索引掃描。 – StackUser

+1

一種可能性是做兩個查詢,每個條件一個,和'UNION'他們在一起 – HoneyBadger

+1

@HoneyBadger可能不是最好的選擇,因爲你會掃描表兩次。 –

回答

0

你嘗試過一個UNION ALL? 選擇... 請將isDeleted在哪裏= 0 UNION ALL 選擇... 請將isDeleted哪裏是空

或者你可以添加一個查詢提示(指數= [INDEXNAME])

也知道,基數將確定SQL是否使用搜索或掃描 - 搜索速度更快,但如果索引不覆蓋所有需要的列,則可能需要密鑰查找。一個好的經驗法則是,如果查詢將返回超過5%的表,那麼SQL將更喜歡掃描。

+0

您的第一條建議將使查詢按照@RaduGheorghiu在評論中提及的方式掃描表格兩次。如果桌子很大,這對性能來說會很昂貴。 –

+1

我讀過的帖子說這個經驗法則只適用於10%或更多。另外,我讀過的帖子說這個百分比沒有「幻數」。我傾向於認爲沒有幻數,因爲它將全部由查詢**成本**確定。成本比*行數*更復雜。是的,基數很重要,但它不是唯一的因素。 –

+0

@John:我的桌子每天都在增長。目前該表格包含50萬條記錄。我預計大概有兩三百萬。 – StackUser

1

您沒有獲得索引查找,因爲您正在獲取表中幾乎93%的行,並且在這種情況下,只是掃描整個索引更快,更便宜。

如果你有性能問題,你應該考慮移除format()函數,特別是當查詢返回很多行時。閱讀more from this blog post

其他選項可能是創建索引視圖並預先彙總數據。這當然會增加更新/插入操作的開銷,所以只有在這種情況經常發生時纔會更新表的更新頻率。