2013-05-27 60 views
27

這是一個關於SQL Server 2008 R2的問題爲什麼臨時表和子查詢之間有巨大的性能差異

我不是DBA,到目前爲止。我是一名Java開發人員,他不得不隨時寫SQL。 (主要嵌入代碼中)。我想知道我在這裏做錯了什麼,如果是的話,我可以做些什麼來避免它再次發生。

Q1:

SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ... 

Q1特徵14聯接

Q2相同Q1,有一個例外。 (SELECT * FROM T1 WHERE condition1)之前執行,並存儲在臨時表中。

這不是一個相關的子查詢。

Q2:

SELECT * INTO #tempTable FROM T1 WHERE condition1 
SELECT something FROM #tempTable JOIN ... 

再次,14連結。

現在讓我感到困惑的是Q1花費了2分鐘(試了幾次,以避免緩存發揮作用),而Q2(兩個查詢相結合)花了2秒!是什麼賦予了?

+3

我的猜測是'SELECT * FROM T1 WHERE condition1'的估計行數非常不準確。將它物化爲'#tempTable'意味着SQL Server確切地知道將返回多少行。你能發佈兩種實際執行計劃的XML版本嗎? –

回答

40

它爲什麼不推薦使用子查詢?

數據庫優化器(無論您使用的是哪個數據庫)不能總是正確地優化此類查詢(使用子查詢)。在這種情況下,優化器的問題是選擇正確的方式來加入結果集。有幾種連接兩個結果集的算法。算法的選擇取決於包含在一個和另一個結果集中的記錄數。如果您加入兩個物理表(子查詢不是物理表),則數據庫可以通過可用的統計信息輕鬆確定兩個結果集中的數據量。如果其中一個結果集是子查詢,那麼要了解它返回的記錄數是非常困難的。在這種情況下,數據庫可能會選擇錯誤的連接查詢計劃,這會導致查詢性能的顯着降低。

使用臨時表重寫查詢旨在簡化數據庫優化器。在重寫的查詢中,所有參與連接的結果集都將是物理表,並且數據庫將輕鬆確定每個結果集的長度。這將允許數據庫選擇所有可能的查詢計劃中保證的最快速度。而且,無論條件如何,數據庫都會做出正確的選擇。用臨時表重寫的查詢在任何數據庫上都能正常工作,這在便攜式解決方案的開發中尤爲重要。此外,重寫的查詢更易於閱讀,更易於理解和調試。

據瞭解,使用臨時表重寫查詢可能會導致一些額外開支的減速:創建臨時表。如果數據庫不會被錯誤地選擇查詢計劃,那麼它將比舊的查詢更快地執行舊的查詢。但是,這種放緩總是微不足道的。通常創建臨時表需要幾毫秒。也就是說,延遲不會對系統性能產生重大影響,通常可以忽略。

重要!不要忘記爲臨時表創建索引。索引字段應包含連接條件中使用的所有字段。

+1

SQL Server查詢引擎在內部創建臨時表,並且您在上面提供的原因並非總是如此.IT取決於很多其他因素,如索引,分段,統計等。 – AnandPhadke

+2

在臨時表上創建索引可提高查詢性能。 – nirupam

+1

你的回答是相當具有誤導性和錯誤的,創建一個臨時表應該只在某些情況下考慮:http://stackoverflow.com/questions/42772428/should-all-sub-queries-be-replaced-with-temporary-tables ?noredirect = 1#comment72660694_42772428 – Arvand

相關問題