2010-04-27 59 views
1

運行SQL Server 2005上查詢的兩個版本時,我們看到了奇怪的現象:需要與SQL Server上的SQL查詢幫助2005

版本答:

SELECT otherattributes.* FROM listcontacts JOIN otherattributes 
ON listcontacts.contactId = otherattributes.contactId WHERE listcontacts.listid = 1234 
ORDER BY name ASC 

版本B:

DECLARE @Id AS INT; 
SET @Id = 1234; 
SELECT otherattributes.* FROM listcontacts JOIN otherattributes 
ON listcontacts.contactId = otherattributes.contactId 
WHERE listcontacts.listid = @Id 
ORDER BY name ASC 

這兩個查詢都返回1000行;版本A平均需要15秒;版本B平均需要4s。 任何人都可以幫助我們理解這兩個SQL版本的執行時間差異嗎?

如果我們調用使用NHibernate通過命名參數此查詢,我們看到通過SQL Server事件探查以下查詢:

EXEC sp_executesql N'SELECT otherattributes.* FROM listcontacts JOIN otherattributes ON listcontacts.contactId = otherattributes.contactId WHERE listcontacts.listid = @id ORDER BY name ASC', 
    N'@id INT', 
    @id=1234; 

...這往往是表現不佳的版本A.

回答

2

試着看看你的查詢的執行計劃。這應該給你更多的解釋你的查詢是如何執行的。

0

可能不是將1234轉換爲與listcontacts.listid相同的類型,然後與每行進行比較,可能是將每行中的值轉換爲與1234相同的值。第一個參數只需要一個第二個需要每行進行一次強制轉換(可能在1000行以上,可能是表中的每一行)。我不確定那個常量會被解釋爲什麼類型,但它可能是'數字'而不是'int'。

如果這是原因,第二個版本更快,因爲它強制1234被解釋爲一個int,因此不需要在每一行中投入值。

但是,正如前面的海報所示,SQL Server Management Studio中顯示的查詢計劃可能會指出一個替代解釋。

0

看到發生了什麼的最好方法是比較執行計劃,其他的一切都是根據問題中提出的有限細節進行推測。

要查看執行計劃,進入SQL Server Management Studio並運行SET SHOWPLAN_XML ON,然後運行查詢版本A,查詢將不會運行,但執行計劃將以XML顯示。然後運行查詢版本B並查看其執行計劃。如果你仍然不能分辨或解決問題,那麼發佈兩個執行計劃,這裏的某個人會解釋它。

2

我還沒有看到執行計劃,但我強烈懷疑他們在這兩種情況下是不同的。您遇到的問題是,如果A(更快的查詢)優化程序知道您用於列表ID(1234)的值,並使用分佈統計信息和索引組合選擇最佳計劃。

在第二種情況下,優化程序無法嗅探該ID的值,因此會生成一個計劃,該計劃對於任何傳入的列表ID都是可接受的。而我所說的可接受的地方並不意味着最佳。

那麼你可以做些什麼來改善這種情況?有幾個選擇這裏:

1)創建一個存儲過程執行如下查詢:

CREATE PROCEDURE富 @Id INT AS SELECT otherattributes * FROM listcontacts JOIN otherattributes ON listcontacts .contactId = otherattributes.contactId WHERE listcontacts.listid = @Id ORDER BY名ASC

GO

這將使優化器嗅探VALU當輸入參數傳入併爲第一次執行產生適當的執行計劃時。不幸的是,它會緩存該計劃,以便稍後再次使用,除非您通常使用類似的選擇性值調用存儲過程,這可能無助於您太多

2)創建一個如上的存儲過程,但將其指定爲WITH RECOMPILE。這將確保存儲過程每次執行時都會重新編譯,從而生成針對此輸入值優化的新計劃。

3)將OPTION(RECOMPILE)添加到SQL語句的末尾。強制重新編譯此語句,並且能夠針對輸入值進行優化

4)將OPTION(OPTIMIZE FOR(@Id = 1234))添加到SQL語句的末尾。這將導致緩存的計劃針對此特定輸入值進行優化。如果這是一個非常普遍的價值,或者最常見的價值觀具有相似的選擇性,但是如果選擇性的分佈更廣泛地傳播,那麼它就不是那麼好。