2010-03-05 34 views
25

我們有以下查詢。使用LEFT OUTER連接需要9秒鐘才能執行。將LEFT OUTER更改爲LEFT INNER會將執行時間縮短爲2秒,並返回相同的行數。由於正在處理與dbo.Accepts表相同數量的行,因此無論連接類型如何,外層爲什麼會延長3倍?左內連接與左外連接 - 爲什麼外層需要更長的時間?

SELECT CONVERT(varchar, a.ReadTime, 101) as ReadDate, 
     a.SubID, 
     a.PlantID, 
     a.Unit as UnitID, 
     a.SubAssembly, 
     m.Lot 
    FROM dbo.Accepts a WITH (NOLOCK) 
LEFT OUTER Join dbo.Marker m WITH (NOLOCK) ON m.SubID = a.SubID 
WHERE a.LastModifiedTime BETWEEN @LastModifiedTimeStart AND @LastModifiedTimeEnd 
    AND a.SubAssembly = '400' 
+23

我沒有意識到有這樣的事情,作爲'左內聯接'。它有什麼作用? – 2010-03-05 19:07:13

+5

我懷疑'LEFT INNER'的'LEFT'被剝離了,它只是一個'INNER JOIN'。 – 2010-03-05 19:08:01

+1

使用SQL Server 2005,我無法使用'LEFT INNER JOIN'運行查詢 - 我在關鍵字'INNER'附近收到「語法錯誤」錯誤。你使用的是什麼版本的SQL Server?如果2005+,你是否在降級兼容級別運行? – 2010-03-05 19:11:44

回答

35

時返回相同的行數是一個事實後,查詢優化器可以事先不知道,每一個在接受行都有一個匹配的行標誌物,可以在這個事實?

如果你連接兩個表A和B,說A有100萬行,B有1行。如果你說A左內聯JOIN B意味着只有匹配的行與 A和B都可以產生,所以查詢計劃可以先掃描B,然後使用索引在A中進行範圍掃描,也許返回10行。但是如果你說A左邊的外部連接B然後至少 A中的所有行必須被返回,所以計劃必須掃描A中的所有內容,而不管它在B中找到什麼。通過使用OUTER連接,您正在消除一種可能的優化。

如果你知道知道 Accepts中的每一行都會在標記中有一個匹配,那麼爲什麼不聲明一個外鍵來強制執行呢?優化器將看到約束條件,如果是可信的,將在計劃中考慮它。

+10

等等......沒有像「左內聯」那樣的東西。它是「左加入」或「左外加入」。 「INNER」已經意味着它是交叉口,交叉口只能是一件事。這就是爲什麼有「OUTER」關鍵字。不知道這個答覆是如何得到19票的,除非我在這裏錯過了一些全新的東西。 – 2014-08-27 23:36:20

+2

@NicholasPufal:由於SQL語法是正確的,['INNER'沒有'LEFT'和'RIGHT'](http://msdn.microsoft.com/en-us/library/ms177634.aspx)。 'LEFT'或'LEFT OUTER'意思相同,'OUTER'是一個可選的標記。關於OP的許多評論已經涵蓋了這一點。但我完全理解蘭迪的意思,我想他明白我的意思。 – 2014-08-28 06:31:32

+0

對不起。我再次閱讀你的答案,你只是根據作者的話說出你的觀點。我的錯。我之前瞭解你的答案完全不同。 – 2014-08-28 10:42:55

28

1)在SQL Server Management Studio中的查詢窗口,運行以下命令:

SET SHOWPLAN_ALL ON

2)運行緩慢的查詢

3)您的查詢將不會運行,但執行計劃將被退回。存儲這個輸出

4)運行查詢

5)你的查詢將不會運行的快速版本,但執行計劃將被退回。存儲此輸出

6)將慢速查詢版本輸出與快速查詢版本輸出進行比較。 7)如果你仍然不知道爲什麼一個更慢,在你的問題中發佈兩個輸出(編輯它),這裏的某個人可以從那裏獲得幫助。

+2

'SET SHOWPLAN_ALL ON'是我今天最喜歡的命令! – 2011-05-03 18:45:42

+2

我覺得這更像是「教一個人釣魚......」的答案。爲此命令upvoted,我將強迫我的所有開發人員學習。 – 2011-07-06 18:44:01

+0

錯誤代碼:1193.未知的系統變量「SHOWPLAN_ALL」。我該如何運行這個命令 – makkasi 2015-11-12 10:34:07

2

等待 - 你真的意味着「相同的行數......正在被處理」或「相同的行數正在返回」?一般來說,外連接會處理更多的行,包括那些沒有匹配的行,即使它返回相同數量的記錄。

+1

對不起,我有點粗心。 「返回」的行數相同。 – 2010-03-05 19:38:29

6

這是因爲在發送結果之前,LEFT OUTER Join正在做比INNER更多的工作。

Inner Join查找ON語句爲真的所有記錄(所以當它創建一個新表時,它只會放入匹配m.SubID = a.SubID的記錄)。然後將這些結果與您的WHERE語句(最後一次修改時間)進行比較。

左外連接...將第一張表中的所有記錄都記錄下來。如果ON語句不正確(m.SubID不等於a.SubID),它只是NULLS該記錄集的第二個表的列中的值。

在最後得到相同數量的結果的原因可能是巧合,因爲在記錄的所有複製之後發生了WHERE子句。

Join (SQL) Wikipedia