2017-05-24 67 views
0

運行以下查詢後:SQL服務器 - 索引未使用

SELECT [hour], count(*) as hits, avg(elapsed) 
FROM myTable 
WHERE [url] IS NOT NULL and floordate >= '2017-05-01' 
group by [hour] 

執行計劃基本上是一個聚集索引掃描的PK(INT,自動遞增,工作的97%)

的事情是:URL上有一個索引(普通索引,因爲我一直在尋找一個精確匹配),floordate的索引還...

爲什麼他們沒有被使用?我怎樣才能加快這個查詢?

PS:表是70M的項目長,這個查詢需要大約9分鐘運行

編輯1
如果我不使用仍然在我的指數(選擇或過濾器)一列,將其使用?通常我也爲clientId(在整個數據庫中大約有300個唯一字符)和hour(24個唯一字符)篩選/篩選...

+2

如果這些列沒有包含在您提到的索引中,那麼列「hour」和「Elapsed」如何處理?查詢將需要在聚集索引中查找以獲取這些值。 –

+3

單個列上的索引不包括整個查詢('hour'和'elapsed'仍然需要查找),如果大多數行具有'url'' NOT NULL',那麼'url'上的索引isn'完全有用。所有這一切都取決於引擎估計將由'floordate> ='2017-05-01'覆蓋多少行以及聚集索引查找是否會直接掃描它。如果你的統計數據過時了,這個估計值可能會大幅下降。在做任何事情之前嘗試更新它們(下一個邏輯步驟是在該索引中包含「INCLUDE」列)。 –

+1

您可以通過count(1)替換count(*),並且它可能有助於提高一些時間。 – SAJ

回答

1

在這種情況下,兩件事會影響SQL Server如何選擇索引。

  1. 指數的選擇性如何。選擇性越高越好。 NULL/NOT NULL過濾器通常具有非常低的選擇性。
  2. 索引中的所有列,也稱爲覆蓋索引。

在您的示例中,如果索引無法覆蓋查詢,則SQL將不得不根據基表查找其他列值。如果您的URL/Floordate組合的選擇性不夠,SQL可能會確定掃描基本表更便宜,而不是從非聚簇索引到基表的大量行進行昂貴的查找。

不知道什麼對你的方案,我建議的指數有以下欄目:

floordate, url, hour; include elapsed 

日期範圍掃描通常比一個NULL/NOT NULL測試更有選擇性。將Floordate移到前面可能會使此索引更適合此查詢。如果SQL確定查詢適用於Floordate和URL,則Hour列可用於Group By操作。由於包含了Elapsed,因此此索引可以完全覆蓋查詢。

您可以在一小時之後包含ClientID以查看是否也有助於您的其他查詢。

只要索引包含所有要解析查詢的列,即使沒有需要的過濾,也可以使用它。一般而言,非聚集索引比基本表格更瘦,比掃描全寬基表要少IO。