2012-10-11 73 views
4

我有一個約100萬行SQL Server上的表。 它有一個ID(PK),一個狀態(int)和一個日期時間列。 另外我在datetime列上創建了一個索引。爲什麼SQL Server不使用非常類似的日期時間查詢索引?

現在我發現了一個效果,我不明白。

SELECT status 
FROM table 
WHERE dateTime BETWEEN '2010-01-01T00:00:00' AND '2010-01-02T12:00:00' 

該語句返回3664行。它運行大約150ms,並且執行計劃顯示它通過密鑰查找執行索引查找。

現在,如果我改變如下(只是更改小時12〜13):

SELECT status 
FROM table 
WHERE dateTime BETWEEN '2010-01-01T00:00:00' AND '2010-01-02T13:00:00' 

此語句返回3667行。它運行大約600毫秒,並且生成計劃顯示它使用主鍵!

我只是不明白它。對於3667和更多的行,它始終使用主鍵,即使搜索速度更快。

有沒有解釋?

+0

嘗試在日期時間字段中的索引中包含「status」列 - 我幾乎保證這樣做,查詢優化器將使用該索引,並且比執行聚簇索引掃描時快得多...... –

回答

5

status未包含在datetime的索引中,因此需要爲每個匹配行執行密鑰查找以檢索此值。

隨着範圍的增長(以及因此需要的查找次數),它估計只是掃描整個(覆蓋)聚集索引以避免查找會更快。您的情況可能不正確。它從一個計劃切換到另一個的點被稱爲the tipping point

您應該檢查估計的行數與實際的行數是否過零(也許某些行與範圍相匹配的行自上次更新以來已被刪除)。

或者也許索引掃描比成本計算假設由於高級碎片或其他原因造成的成本假設更昂貴,或者由於某些其他原因,costing assumptions並未反映您環境中的實際相對性能。

+1

@ pst - 因爲時間範圍越寬,估計的行越大,因此達到臨界點。執行CI掃描的查詢包括額外的一小時。 –

+0

我在創建新索引之前刪除了所有更多索引和統計信息。確實有一個「臨界點」(在這種情況下爲'2010-01-02T13:00:00')。對於每一個較大的時期,它總是使用主鍵,這使得它顯然變慢。雖然,我不明白,因爲索引搜索應該更快,因爲主鍵總是要梳理每一行,對嗎? – Powerslave

+2

@Powerslave - 它假定執行(主要是順序IO)掃描比大量隨機IO查找更快,並相應地解決了兩個選項。它可以在一小部分桌子上從一個切換到另一個。這在我的答案中的轉折點鏈接中有更多的討論。成本假設假定查詢將使用冷高速緩存執行,因此所有數據都需要從光盤中引入。 –

相關問題