SQL JOIN和IN的性能哪个更好?

234

我有一个情况,在这种情况下使用JOIN或IN将给我正确的结果... 通常哪个具有更好的性能,为什么?在多大程度上取决于您使用哪个数据库服务器?(FYI我正在使用MSSQL)

我有一个案例,在这个案例中使用JOIN或IN都可以给我正确的结果。通常哪个性能更好,为什么?这在多大程度上取决于您使用的数据库服务器?(FYI我正在使用MSSQL)

我实际上是在寻找一篇不同的文章,之前我在研究类似的东西时用过,然后无意中发现了这篇。 - AdaTheDev
抱歉可能重复了...在我搜索时没有找到那个问题。 - Polaris878
请注意,此问题直接询问性能差异(这取决于优化)。然而,JOIN和IN具有不同的语义!由于SQL是一种声明性语言,我建议使用适合您用例的方式,并依赖底层查询优化器(尽可能长时间)。因此,如果可能,请先检查哪种方式更适合(在这种情况下可能是IN甚至是EXISTS)。 - P. Rathje
6个回答

267

一般来说,INJOIN 是不同的查询,可能会产生不同的结果。

SELECT  a.*
FROM    a
JOIN    b
ON      a.col = b.col

不同于

SELECT  a.*
FROM    a
WHERE   col IN
        (
        SELECT  col
        FROM    b
        )

除非b.col是唯一的,否则不要这样做。

然而,这是第一个查询的同义词:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT col
        FROM    b
        )
ON      b.col = a.col
如果连接列是UNIQUE并标记为这样,在SQL Server中这两个查询将产生相同的计划。如果不是,那么在具有DISTINCT的情况下,INJOIN更快。请参阅我博客上的文章以获取性能详细信息:

是的,如果连接列是唯一的(在我的情况下确实如此),那么它们执行相同是有意义的。 - Polaris878
1
类似的问题,我应该使用IN(SELECT DISTINCT ...)还是仅仅使用IN(SELECT ...)? - moo
10
@orlandu63说:“IN”意味着“DISTINCT”。SQL Server足够聪明,会注意到这一点,并为两个查询生成相同的计划。不过,我不确定其他RDBMS会有什么不同的行为。 - Quassnoi
1
IN和JOIN是不同的查询,可能会产生不同的结果。 即使b.col不是唯一的,您能解释一下为什么在这种情况下会生成不同的结果吗? - Abhijeet
1
https://explainextended.com/2009/06/16/in-vs-join-vs-exists/ 这篇文章对我很有帮助,谢谢。 - Abbas Galiyakotwala

11

这个帖子已经很旧了,但仍经常被提及。就我个人的口味而言,它有点不完整,因为还有另一种使用 EXISTS 关键字查询数据库的方法,我发现它通常比较快。

因此,如果您只对表 a 中的值感兴趣,可以使用以下查询:

SELECT  a.*
FROM    a
WHERE   EXISTS (
    SELECT  *
    FROM    b
    WHERE   b.col = a.col
    )

如果col没有被索引,差异可能会很大,因为数据库不必在b中找到所有具有相同col值的记录,它只需找到第一条记录。如果在b.col上没有索引且b中有很多记录,则可能导致表扫描。使用IN或JOIN将导致完全表扫描,而使用EXISTS将只是部分表扫描(直到找到第一个匹配记录)。

如果b中有许多具有相同col值的记录,则您还会浪费大量内存将所有这些记录读入临时空间,仅仅是为了发现条件已满足。使用exists通常可以避免这种情况。

我经常发现即使有索引,EXISTS也比IN更快。这取决于数据库系统(优化程序)、数据以及最后但并非最不重要的使用的索引类型。


5
在 MSSql 中,存在(EXISTS)优于 IN(子查询)的观点似乎不正确。更多信息请参见: http://explainextended.com/2009/06/16/in-vs-join-vs-exists/在这里可以看到:“许多人认为 EXISTS 比 IN 更有效率,因为 EXISTS 只返回一行结果。但是,在 SQL Server 上这并不正确。如上面的例子所示,EXISTS 和 IN 产生完全相同的执行计划。这是因为 EXISTS 比 IN 更灵活。IN 可以通过使用简单的 WHERE 条件和等值连接重写为 EXISTS,但反之则不行。” - Micaël Félix

10

这个很难说 - 为了真正找出哪种方法更好,你需要实际测试执行时间。

一般而言,如果你在外键列上有索引,并且只使用(或大多数使用)INNER JOIN条件,那么JOIN会稍微快一些。

但是一旦你开始使用OUTER JOIN,或者缺少外键索引,IN可能会更快。

Marc


我也是这么想的...因为JOIN似乎是更常见的情况,更有可能被优化。 - Polaris878

5
一个关于逻辑差异的有趣文章:SQL Server:JOIN vs IN vs EXISTS - 逻辑差异 我相信,如果假设关系和索引得到维护,则连接操作总体上会更好(与其他操作相比需要更多的努力)。如果你从概念上考虑,那么这就是两个查询和一个查询之间的区别。
你需要将其连接到查询分析器并尝试并查看差异。还要查看查询执行计划并尝试最小化步骤。

3
每个数据库实现方式都不同,但是它们解决的问题大多相同。如果你正在使用MSSQL,可以查看生成的执行计划。您可以通过打开分析器和执行计划来完成此操作。当您运行此命令时,会给出文本版本。
我不确定您使用的MSSQL版本,但您可以在查询分析器中获取图形版本的SQL Server 2000。我相信这种功能在更高版本的SQL Server Studio Manager中某处潜藏着。
查看执行计划。尽可能避免表扫描,除非您的表很小,在这种情况下,表扫描比使用索引更快。阅读有关每个不同情况产生的不同连接操作的信息。

1

优化器应该足够智能,以便在正常查询中以任何一种方式都给出相同的结果。检查执行计划,它们应该给出相同的结果。如果不是这样,我通常认为JOIN更快。然而,所有系统都是不同的,因此您应该在您的系统上对代码进行分析以确保。


5
应该这样做吗?也许。但它确实这样做了吗?不是的。请看我的帖子。 - cletus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接