2017-09-25 84 views
1

下面有兩個查詢除了JOIN到mjnEmployeeDepartment以外是相同的。第一個查詢使用LEFT OUTER JOIN,第二個使用INNER JOIN。他們都返回相同的數據,但INNER JOIN需要4.5分鐘執行,而LEFT OUTER JOIN需要4秒。任何人都可以提出可能發生的事情嗎?內部加入殺死查詢性能

我正在運行SMS 2017中針對SQL 2012數據庫的代碼。

Select 
Count(*) --23878 00:00:00 

From 
     dbo.mjnEmployee as e 
       Inner Join dbo.mjnEmployeeStatus as s 
        on e.EmployeeID = s.EmployeeID 
       Inner Join dbo.mjnEmployeeEmploymentInfo as RankNo 
        On e.EmployeeId = RankNo.EmployeeID 
       Inner Join dbo.mjnEmployeeOfficeAssociation as Office 
        On e.EmployeeId = Office.EmployeeID 
       Inner Join dbo.mjnEmployeeEmploymentInfo as TrackNo 
        On e.EmployeeId = TrackNo.EmployeeID 
       Inner Join dbo.mjnEmployeeUnit as Unit 
        on e.EmployeeID = Unit.EmployeeID 
        And Unit.Iteration = 1 

       Left Outer Join dbo.mjnEmployeeDepartment as Department 
        on e.EmployeeID = Department.EmployeeID 

       Left Outer Join dbo.mjnEmployeeAssociation as Supervisor 
        On e.EmployeeId = Supervisor.ObjectEmployeeId 
        and Supervisor.EmployeeAssociationType = 2 
       Left Outer Join dbo.mjnEmployeeAssociation as Manager 
        On Manager.ObjectEmployeeId = e.EmployeeId 
        and Manager.EmployeeAssociationType = 1 
       Left Outer Join dbo.mjnEmployeeAssociation as Assistant 
        On e.EmployeeId = Assistant.ObjectEmployeeId 
        and Assistant.EmployeeAssociationType = 3 
       Left Outer Join dbo.mjnEmployeeAssociation as Advisor 
        On e.EmployeeId = Advisor.ObjectEmployeeId 
        and Advisor.EmployeeAssociationType = 4 

Select 
Count(*) --23878 00:04:37 

From 
     dbo.mjnEmployee as e 
       Inner Join dbo.mjnEmployeeStatus as s 
        on e.EmployeeID = s.EmployeeID 
       Inner Join dbo.mjnEmployeeEmploymentInfo as RankNo 
        On e.EmployeeId = RankNo.EmployeeID 
       Inner Join dbo.mjnEmployeeOfficeAssociation as Office 
        On e.EmployeeId = Office.EmployeeID 
       Inner Join dbo.mjnEmployeeEmploymentInfo as TrackNo 
        On e.EmployeeId = TrackNo.EmployeeID 
       Inner Join dbo.mjnEmployeeUnit as Unit 
        on e.EmployeeID = Unit.EmployeeID 
        And Unit.Iteration = 1 

       Inner Join dbo.mjnEmployeeDepartment as Department 
        on e.EmployeeID = Department.EmployeeID 

       Left Outer Join dbo.mjnEmployeeAssociation as Supervisor 
        On e.EmployeeId = Supervisor.ObjectEmployeeId 
        and Supervisor.EmployeeAssociationType = 2 
       Left Outer Join dbo.mjnEmployeeAssociation as Manager 
        On Manager.ObjectEmployeeId = e.EmployeeId 
        and Manager.EmployeeAssociationType = 1 
       Left Outer Join dbo.mjnEmployeeAssociation as Assistant 
        On e.EmployeeId = Assistant.ObjectEmployeeId 
        and Assistant.EmployeeAssociationType = 3 
       Left Outer Join dbo.mjnEmployeeAssociation as Advisor 
        On e.EmployeeId = Advisor.ObjectEmployeeId 
        and Advisor.EmployeeAssociationType = 4 
+0

我的第一個想法是缺乏索引。 – duffymo

+0

我也是達菲,但不會缺少索引影響左連接以及內連接?另外,當我查看執行計劃時,SMS不會提示任何新的索引。 –

+2

您應該[至少包含實際的執行計劃](https://stackoverflow.com/a/7359705/1260204),您可以使用[粘貼計劃](https://www.brentozar.com/pastetheplan /)並在你的問題中分享鏈接。另外[嘗試自己讀](https://stackoverflow.com/a/759097/1260204),也許你可以找出與您的查詢性能問題(S)。最後,包括[schema DDL](https://en.wikipedia.org/wiki/Data_definition_language)以及正在執行的查詢。 – Igor

回答

-1

您需要查看內連接和外連接之間的區別。實質上,內部聯接將爲兩個表提供共同的行,其中外部聯接將賦予表A中的所有行和表B中匹配的所有行。

這可能解釋了爲什麼你的內部連接速度更快(雖然不知道數據很難說)。

的差異在其他的問題在這裏都說明真的很好:

What is the difference between "INNER JOIN" and "OUTER JOIN"?

+0

INNER JOIN是緩慢的。這就是我困惑的原因。他們都會返回相同的數據,但會讓內部連接的時間延長將近100倍。 –

+0

你的問題表明他們都返回相同的數據,但INNER JOIN需要4分鐘才能執行,而LEFT OUTER JOIN需要4.5分鐘,因此我的回答爲 – Ceaser1980

+0

BAH!我打算輸入4 SECONDS。我的錯。 –

0

這似乎是,在下面用表的連接失蹤導致繁殖與先前的結果集的所有行條款,

Inner Join dbo.mjnEmployeeDepartment as Department 
        on e.EmployeeID = Department.EmployeeID 

是否有任何其他表具有此列?如果是,那麼需要使用。

+0

行不重複。這兩個版本的查詢都返回完全相同的數據。 –

+0

它不是相同的數據,在第一個查詢其左外部聯接,並在第二個查詢它的內部聯接在這張表 –

+0

它是相同的數據。在這種情況下,兩個表中的數據都是1-1完全匹配,所以左連接與內連接返回相同的確切數據集。差異在於優化器選擇的執行計劃中。 –

0

我們結束了使用重新排序表格和使用FORCESEEK優化器提示的組合。我們將條件連接表移到所有內部連接表之後,並在部門表之後添加WITH(FORCESEEK)。現在像冠軍一樣運行。