哪个SQL查询更快?在Join条件上进行筛选还是使用Where子句?
哪个SQL查询更快?在Join条件上进行筛选还是使用Where子句?
比较这两个查询。将过滤器放在连接条件还是在WHERE子句中更快?我一直觉得将过滤器放在连接条件中更快,因为它能在最早的时刻减少结果集,但我不确定。
我将进行一些测试,但我也想听听哪种更容易阅读的意见。
查询1:
选择所有
从表A a
内连接表XRef x
在a.ID = x.TableAID上
内连接表B b
在x.TableBID = b.ID上
WHERE a.ID = 1 /* <-- 过滤器在这里? */
查询2:
选择所有
从表A a
内连接表XRef x
在a.ID = x.TableAID上
并且a.ID = 1 /* <-- 还是在这里过滤器? */
内连接表B b
在x.TableBID = b.ID上
编辑:
我进行了一些测试,结果显示实际上非常接近,但WHERE子句稍微更快!=)
我完全同意在WHERE子句上应用过滤器更有意义,我只是对性能影响感到好奇。
经过时间的比较WHERE条件:143016毫秒
经过时间的比较JOIN条件:143256毫秒
测试:
SET NOCOUNT ON;
DECLARE @num INT,
@iter INT
SELECT @num = 1000, -- TableA和TableB中的记录数,交叉表通过从A到B进行CROSS JOIN填充
@iter = 1000 -- 要执行的选择迭代次数
DECLARE @a TABLE (
id INT
)
DECLARE @b TABLE (
id INT
)
DECLARE @x TABLE (
aid INT,
bid INT
)
DECLARE @num_curr INT
SELECT @num_curr = 1
WHILE (@num_curr <= @num)
BEGIN
INSERT @a (id) SELECT @num_curr
INSERT @b (id) SELECT @num_curr
SELECT @num_curr = @num_curr + 1
END
INSERT @x (aid, bid)
SELECT a.id,
b.id
FROM @a a
CROSS JOIN @b b
/*
测试
*/
DECLARE @begin_where DATETIME,
@end_where DATETIME,
@count_where INT,
@begin_join DATETIME,
@end_join DATETIME,
@count_join INT,
@curr INT,
@aid INT
DECLARE @temp TABLE (
curr INT,
aid INT,
bid INT
)
DELETE FROM @temp
SELECT @curr = 0,
@aid = 50
SELECT @begin_where = CURRENT_TIMESTAMP
WHILE (@curr < @iter)
BEGIN
INSERT @temp (curr, aid, bid)
SELECT @curr,
aid,
bid
FROM @a a
INNER JOIN @x x
ON a.id = x.aid
INNER JOIN @b b
ON x.bid = b.id
WHERE a.id = @aid
SELECT @curr = @curr + 1
END
SELECT @end_where = CURRENT_TIMESTAMP
SELECT @count_where = COUNT(1) FROM @temp
DELETE FROM @temp
SELECT @curr = 0
SELECT @begin_join = CURRENT_TIMESTAMP
WHILE (@curr < @iter)
BEGIN
INSERT @temp (curr, aid, bid)
SELECT @curr,
aid,
bid
FROM @a a
INNER JOIN @x x
ON a.id = x.aid
AND a.id = @aid
INNER JOIN @b b
ON x.bid = b.id
SELECT @curr = @curr + 1
END
SELECT @end_join = CURRENT_TIMESTAMP
SELECT @count_join = COUNT(1) FROM @temp
DELETE FROM @temp
SELECT @count_where AS count_where,
@count_join AS count_join,
DATEDIFF(millisecond, @begin_where, @end_where) AS elapsed_where,
DATEDIFF(millisecond, @begin_join, @end_join) AS elapsed_join
哪个SQL查询更快?基于连接条件的过滤还是基于WHERE子句的过滤?
当涉及到性能时,它们是相同的(并且产生相同的执行计划)。
从逻辑上讲,如果你用LEFT JOIN替换INNER JOIN,应该选择仍然有意义的操作。
在你的情况下,可以这样实现:
SELECT *
FROM TableA a
LEFT JOIN TableXRef x
ON x.TableAID = a.ID
AND a.ID = 1
LEFT JOIN TableB b
ON x.TableBID = b.ID
或者这样实现:
SELECT *
FROM TableA a
LEFT JOIN TableXRef x
ON x.TableAID = a.ID
LEFT JOIN TableB b
ON b.id = x.TableBID
WHERE a.id = 1
前一个查询将只返回与a.id = 1匹配的实际结果,因此后一种语法(带有WHERE子句)在逻辑上更一致。
当我绘制集合时,我明白了为什么第二种情况更一致。在前一个查询中,约束条件a.id = 1只适用于交集部分,而不适用于排除交集的左侧部分。
在第一个示例中,可能存在a.id != 1的行,而第二个示例只有a.id = 1的行。
你的语言不清楚。"从逻辑上讲,你应该选择仍然有意义的操作..."和"在逻辑上更一致"没有意义。你能重新表达一下吗?
在SQL查询中,有两种常用的筛选数据的方法,即使用JOIN/ON操作和使用WHERE子句。JOIN/ON操作用于连接表,而WHERE子句用于筛选结果。这两种方法可以根据具体情况进行不同的使用,但是我个人认为总是感觉有些不对劲。只有在性能成为问题时,才需要考虑这样的“优化”。但是这样的回答似乎并没有解答问题。
这个问题的出现原因是有人想知道在SQL查询中,使用JOIN条件进行筛选还是使用WHERE子句进行筛选,哪种方法更快。下面将介绍一些关于这个的问题和解决方法。
有些人认为在大多数情况下,使用WHERE子句进行筛选会更快。因为通过使用WHERE子句,可以在连接之前先筛选出满足条件的数据,减少了需要连接的数据量。这样可以减少连接操作的时间和资源消耗。而使用JOIN/ON操作进行筛选,则需要先连接表,然后再筛选数据,可能会增加查询的时间和资源消耗。
然而,也有一些人认为使用JOIN条件进行筛选会更快。因为使用JOIN条件可以利用数据库的索引,提高查询的效率。而使用WHERE子句进行筛选,则可能无法充分利用索引,导致查询效率较低。
为了解决这个问题,可以使用不同的方法进行测试和比较。可以编写两个不同的SQL查询语句,一个使用JOIN/ON操作进行筛选,另一个使用WHERE子句进行筛选。然后通过执行这两个查询语句,并比较它们的执行时间和资源消耗来判断哪个方法更快。
下面是一个示例代码,用于比较使用JOIN/ON操作和使用WHERE子句进行筛选的查询效率:
-- 使用JOIN/ON操作进行筛选
SELECT *
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.column1 = 'value';
-- 使用WHERE子句进行筛选
SELECT *
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table2.column1 = 'value';
通过执行以上两个查询语句,并比较它们的执行时间和资源消耗,可以得出哪个方法更快的结论。
总之,在选择使用JOIN/ON操作还是WHERE子句进行筛选时,需要根据具体情况进行考虑。可以通过测试和比较来确定哪种方法更适合当前的查询需求。同时,还可以考虑其他的优化方法,如创建合适的索引、优化查询语句等,来提高查询的性能。
在内连接中,将条件放在哪里并不重要。SQL编译器会将两者都转化为执行计划,其中过滤发生在连接之下(即,就像过滤表达式出现在连接条件中一样)。
而对于外连接来说,过滤条件的位置会改变查询的语义。
所以在内连接中,它首先计算过滤条件,然后将过滤条件的输出与另一个表进行连接,或者首先连接两个表,然后应用过滤条件?
Rusanu-您能详细说明一下外连接的语义如何改变吗?根据过滤条件的位置,我得到了不同的结果,但无法理解为什么。
在外连接中,如果JOIN条件不匹配,所有与连接表相关的列都会得到NULL值。过滤条件不会满足NULL值,并消除行,将外连接实际上转变为内连接。
根据您的评论,我实现了所需的优化。我的更改是将"WHERE x.TableAID = a.ID or x.TableAID is null"更改为"ON x.TableAID = a.ID"。改变了外连接中过滤条件的位置后,编译器知道先过滤再连接,而不是先连接再过滤。它还能够使用该列上的索引,因为它不需要匹配NULL值。查询响应时间从61秒变为2秒。