我们有以下查询。使用LEFT OUTER连接需要9秒才能执行。将LEFT OUTER更改为LEFT INNER会将执行时间减少到2秒,并返回相同行数。由于正在处理dbo.Accepts表中的相同行数,因此无论连接类型如何,为什么外部需要更长的时间?
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'
答案 0 :(得分:35)
返回相同行数的事实是事实,查询优化器事先无法知道Accepts中的每一行在Marker中都有匹配的行,可以吗?
如果连接两个表A和B,则说A有100万行,B有1行。如果你说A LEFT INNER JOIN B,则表示只有匹配 A和B的行才能生成,因此查询计划可以先自由扫描B,然后使用索引在A中进行范围扫描,也许返回10行。但是如果你说A LEFT OUTER JOIN B然后至少必须返回A中的所有行,那么计划必须扫描A中的所有内容,无论它在B中找到什么。通过使用OUTER加入你正在消除一种可能的优化。
如果知道,接受中的每一行都会在Marker中匹配,那么为什么不声明外键来强制执行此操作呢?优化器将看到约束,如果受信任,将在计划中考虑它。
答案 1 :(得分:28)
1)在SQL Server Management Studio的查询窗口中,运行命令:
SET SHOWPLAN_ALL ON
2)运行慢速查询
3)您的查询将无法运行,但将返回执行计划。存储此输出
4)运行查询的快速版本
5)您的查询将无法运行,但将返回执行计划。存储此输出
6)将慢查询版本输出与快速查询版本输出进行比较。
7)如果你仍然不知道为什么一个较慢,请在你的问题中发布两个输出(编辑它),这里有人可以从那里帮助。
答案 2 :(得分:6)
这是因为在发送结果之前,LEFT OUTER Join比INNER Join做更多的工作。
Inner Join查找ON语句为true的所有记录(因此,当它创建新表时,它只会放入与m.SubID = a.SubID匹配的记录)。然后它将这些结果与您的WHERE语句(您上次修改时间)进行比较。
左外连接...获取第一个表中的所有记录。如果ON语句不为真(m.SubID不等于a.SubID),它只是NULLS该记录集的第二个表的列中的值。
由于WHERE子句在所有复制记录之后发生,因此最终得到相同数量结果的原因可能是巧合。
答案 3 :(得分:2)
等等 - 您是否真的意味着“相同数量的行...正在<强>处理”或“相同数量的行正在返回” ?通常,外连接将处理更多行,包括那些没有匹配的行,即使它返回相同数量的记录。