2011-01-20 79 views
3

我有一個SQL Server 2005中的大表,我必須通過非集羣密鑰選擇記錄,並且我試圖儘可能優化此過程。不一致的SQL Server執行計劃密鑰查找

表中有很多列,我在三個不同的列上添加了非聚簇索引。

SELECT * FROM table WHERE Field1 = 10; 
SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field3 = 'A'; 

Field 1和字段2是整數字段,字段3是一個varchar。

當我要求從SQL Server這三個查詢的估計查詢執行計劃,我得到基本相同的計劃,每個:

SELECT -> Nested Loop -> Index Seek 
         -> Key Lookup 

但我發現,那個執行時間有很大的不一致。具體而言,第二個查詢佔總查詢成本的98%。其執行計劃與其他計劃相同,只是與索引搜索相比,密鑰查找步驟的成本爲100%。在另外兩個查詢中,它接近50%。

我知道Key Lookup是不受歡迎的,可以通過在索引中添加列來避免這些額外的列被查找。但是,在這種情況下,我希望表中的所有列都返回給我,所以將它們全部添加到索引是沒有意義的。但是,一個索引如何導致密鑰查找操作比另一個密鑰查找花費更多的時間呢?

回答

1

但怎麼可能一個索引導致關鍵 查找操作採取了這麼多 長於另一個鍵查找?

這一切都取決於預期密鑰長度的當前統計。

查詢優化器(QO)通過查看索引的統計信息進行工作。fieldb上的索引可以具有100的平均基數,而其他字段上的索引的平均基數爲10000(具體爲100倍)。所以它給了你一個相對的指示,基於averaged計劃。

要查看詳細信息,請始終打開統計信息*,但實際上只會給出具體值的actual execution time。在某些方面,如果訪問變量是隨機的,那麼QO可以長期更準確。

考慮這兩個查詢的情況下

SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field2 = 42; 

比方說,假設42是在所有記錄80%的人使用一個特殊的代碼。 40是唯一一個記錄中使用的唯一代碼。您不能指望QO爲每個行顯示不同的估計行數?但是,如果您運行了查詢,除非涉及參數化/計劃緩存,否則第二位可能會使用clustered index掃描表而不是執行80%(昂貴)的書籤查找。

*打開統計報告

set statistics io on 
set statistics time on 
0

我見過幾種情況,其中「查詢成本(相對於批次)」的百分比可以誤導說至少。

更好地看看與io和時間統計相關的實際執行計劃,以瞭解真正發生的事情。

set statistics io on 
set statistics time on 

SELECT * FROM table WHERE Field1 = 10; 
SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field3 = 'A'; 

然後看邏輯讀,CPU時間和返回每個查詢經過的時間。

2

成本未必與時間有關,而是與資源消耗密切相關。如果沒有看到查詢,知道表格結構以及列中包含的數據的組成,很難真正地說出您的情況。但是,由您的標準匹配的記錄數量可能會在不同的查詢計劃中產生成本差異。

關於表格的索引,如果您可以在索引中包含儘可能多的條件列,那麼您可能會過得更好。首先,根據您的數據,您可以通過索引最具選擇性的列(最有可能消除大部分數據的列)來獲得更好的效果。 (但是,情況並非如此,特別是如果您與其他表格結合使用,對結果進行排序等)。您可以根據需要添加其他列或者添加其他列。創建索引時,可以使用「包含」子句向索引添加選擇性較低的「where」列,以減少所需的鍵查找次數。