2011-10-24 365 views
1

原始查詢我試圖改寫:重寫SQL查詢與嵌套子查詢

SELECT Table1.* 
FROM Table1 
INNER JOIN Table2 ON Table2.[IDENTITY]=Table1.ID 
WHERE Table2.Field1 = @value AND Table2.Field2 = '1' AND Table1.ID in 
(
    select Table1.ID from Table1 where Table1.Number in 
    (select Table1.Number from Table1 where [email protected]) 
) 

注:在實際的查詢,我列出的所有列,而不是使用表1的*

此查詢有點混亂,特別是因爲我改變了張貼的名字等。簡而言之,它需要獲取傳入的ID並找到具有該ID的所有Table1.Number字段。 Number和ID之間有多對一的關係。因此,一旦找到所有數字,我需要找到使用任何這些數字的ID的總列表。

當我統計一下了,當我運行查詢,我得到

Table 'Table1'. Scan count 3873, logical reads 135255, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Table2'. Scan count 0, logical reads 7995, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

我覺得罪魁禍首就是嵌套子查詢。我一直試圖用一種不同的方式寫一段時間,但我似乎無法完全弄清楚。我將第二個嵌套查詢重寫爲:

WHERE Table2.Field1 = @value AND Table2.Field2 = '1' AND Table1.ID in 
(
    select Table1.ID from Table1 
    INNER JOIN Table1 AS Table3 ON Table1.Number = Table3.Number 
    where [email protected] 
) 

不幸的是,這導致了相同的統計數據。我無法弄清楚如何刪除第二個「in」語句。

這是最好的方法嗎?有更好的嗎?我是對的,這種子查詢性能非常差,從而導致IO統計數據顯示的高掃描和邏輯讀取?

編輯:原始查詢使用Table2。[IDENTITY] = Table1.MessageID。這應該是Table2。[IDENTITY] = Table1.ID。我更新了上述查詢以反映這一點。

回答

2

我相信你是正確的,嵌套子查詢導致你所看到的統計數據。當你有一個值轉換成這樣的集合時,我經常發現性能最佳的解決方案是將子查詢的結果推入臨時表中,然後反向加入。這可以防止子查詢的基於行的執行,並會顯着提高您的性能。

子查詢的內容引用靜態語句變量,但不引用外部語句中的任何元素。這意味着它不是一個相關的子查詢,我們只是對每一行反覆執行相同的操作。當你看到像這樣的子查詢時,這是一個簡單的優化選擇,可以將操作移到select之外,並以更合適的方式引用數據。

對於例如,你提供你會做這樣的事情

select distinct Table1.ID 
INTO #myTemp 
from Table1 where Table1.Number in 
(select Table1.Number from Table1 where [email protected]) 

這會變成你的初始查詢到

SELECT Table1.* 
FROM Table1 
INNER JOIN Table2 ON Table2.[IDENTITY]=Table1.MessageID 
INNER JOIN #myTemp a on Table1.ID = a.ID 
WHERE Table2.Field1 = @value AND Table2.Field2 = '1' 

我假設你正在使用SQL2008 R2使您的語法可能有所不同取決於你的RDBMS。

+0

非常感謝幫助。在原始文章中發現了一個小的錯字(MessageID應該是ID)。你的改變使我下降到1掃描和1110邏輯讀取。 – Equixor