2017-09-25 79 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)。现在像冠军一样运行。