JOIN 或 Correlated 子查询与 exists 子句,哪个更好

Posted

技术标签:

【中文标题】JOIN 或 Correlated 子查询与 exists 子句,哪个更好【英文标题】:JOIN or Correlated subquery with exists clause, which one is better 【发布时间】:2010-07-22 05:02:05 【问题描述】:
select * 
from ContactInformation c 
where exists (select * from Department d where d.Id = c.DepartmentId )

select * 
from ContactInformation c 
inner join Department d on c.DepartmentId = d.Id  

这两个查询都给出相同的输出,这在性能明智的联接或与存在子句的关联子查询中是好的,哪个更好。

编辑:-是否有连接方式,以提高性能:- 在上述 2 个查询中,我想要来自部门的信息以及联系信息表

【问题讨论】:

【参考方案1】:

一般来说,EXISTS 子句是因为您可能需要 DISTINCT 进行 JOIN 才能给出预期的输出。例如,如果 ContactInformation 行有多个 Department 行。

在您上面的示例中,SELECT *:

也表示不同的输出,因此它们实际上并不等效 使用索引的可能性较小,因为您要拉出所有列

也就是说,即使列列表有限,他们也会给出相同的计划:直到您需要 DISTINCT...这就是我说“EXISTS”的原因

【讨论】:

编辑:- 是否有用于连接的交替网方式,以提高性能:- 在上述 2 个查询中,我想要来自部门的信息以及联系信息表【参考方案2】:

您需要衡量和比较 - 没有哪个黄金法则会更好 - 这取决于您系统中的太多变量和事物。

在 SQL Server Management Studio 中,您可以将两个查询放在一个窗口中,从“查询”菜单中选择 Include actual execution plan,然后一起运行它们。

您应该比较它们的执行计划以及花费在一个或另一个查询上的时间百分比。在这种情况下,两者最有可能接近 50%。如果不是 - 那么您知道这两个查询中哪一个执行得更好。

您可以从Simple-Talk 了解有关 SQL Server 执行计划的更多信息(甚至下载免费电子书) - 强烈推荐。

【讨论】:

【参考方案3】:

我假设您打算在第二个查询中将 DISTINCT 关键字添加到 SELECT 子句(或者,不太可能,部门只有一个联系人)。

首先,始终从“逻辑”考虑开始。 EXISTS 构造可以说更直观,所以,所有“物理”的东西都是平等的,我会同意的。

其次,总有一天您需要移植此代码,不一定要移植到不同的 SQL 产品,而是说相同的产品但使用不同的优化器。一个体面的优化器应该认识到两者是等价的并提出相同的理想计划。考虑到,理论上,EXISTS 构造更容易发生短路。

第三,使用相当大的数据集对其进行测试。如果性能不可接受,请开始考虑“物理”方面的考虑(但我建议您始终将“逻辑纯”代码保留在 cmets 中,以备将来完美优化器到来时使用 :)

【讨论】:

【参考方案4】:

您的第一个查询应该输出部门列,而第二个不应该。

如果您只对 ContactInformation 感兴趣,这些查询是等效的。您可以同时运行它们并检查查询执行计划以查看哪个运行得更快。例如,在 mysql 上,where exists 对可以为空的列更有效,而inner join 在两个列都不能为空的情况下表现更好。

【讨论】:

以上是关于JOIN 或 Correlated 子查询与 exists 子句,哪个更好的主要内容,如果未能解决你的问题,请参考以下文章

使用“相关”子查询进行高效连接

SELECT 中的子查询或 JOIN 中的子查询?

MySQL 子查询与 LIMIT 与 JOIN

Mysql JOIN 子查询

将 GROUPED BY SUM 查询与其他查询链接(使用 JOIN 或子查询)

将多个 self JOIN 转换为窗口函数或子查询 (SQL)