假设我有以下T-SQL代码:
SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId;
WHERE b.IsApproved = 1;
下面的一个也返回同一组的列:
SELECT * FROM Foo f
INNER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
这可能不是最好的情况下,样本在这里,但有这两个之间的性能差异?
假设我有以下T-SQL代码:
SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId;
WHERE b.IsApproved = 1;
下面的一个也返回同一组的列:
SELECT * FROM Foo f
INNER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
这可能不是最好的情况下,样本在这里,但有这两个之间的性能差异?
不,查询优化器是足够聪明,选择这两个例子相同的执行计划。
您可以使用SHOWPLAN
检查执行计划。
不过,你应该把所有加入的连接ON
子句和所有限制WHERE
子句。
只是要小心与外连接的区别。 查询,其中的过滤器b.IsApproved
(右侧表,酒吧)被添加到ON
的条件JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
不一样放置过滤器在WHERE
子句:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
由于对“失败”外连接到Bar
(即在没有b.BarId
的f.BarId
),这将离开b.IsApproved
为NULL
的所有这些失败的加入行,然后将这些行会被过滤掉。
看待这个另一种方式是,对于第一个查询, LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
总是会返回左表中的行,因为LEFT OUTER JOIN
保证左表中的行会,如果加入失败,甚至被退回。 然而,添加的效果(b.IsApproved = 1)
到LEFT OUTER JOIN
条件是为NULL任何右表列时(b.IsApproved = 1)
为假,即,作为每通常施加到相同的规则LEFT JOIN
条件(b.BarId = f.BarId)
更新 :要完成康拉德提出的问题,一个可选的过滤器相当于LOJ将是:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
即WHERE
子句中需要考虑两个条件是否加入失败(NULL)
和过滤器是被忽略,并且其中加入成功,必须应用滤镜。 ( b.IsApproved
或b.BarId
可以为被测试NULL
)
我已经把SqlFiddle一起在这里这表明了各个展示位置之间的差异b.IsApproved
过滤相对于JOIN
。
SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId
WHERE b.IsApproved = 1;
这是更好的形式去。 这是很容易阅读和便于修改。 在商业世界,这是你想要去什么。 至于性能,他们是相同的,但。
我已经显得有些情况下优化是不够聪明,甚至在最近的版本MSSQL的 - 而且性能差异是怪物。
但是,这是一个例外,大部分时间SQL Server优化将解决这个问题,并得到正确的计划。
因此,使用十个分量在需要的时候子句和优化的地方优化滤波器的政策。
我刚跑一个查询的一个测试针对四个表 - 一个主表具有三个内部连接和总共四个paramters,并比较这两种方法的执行计划(使用过滤标准中的JOIN接通,然后还WHERE子句)。
执行计划是完全一样的。 我跑这个SQL Server 2008 R2上。