选择中的左连接与子查询的奇怪问题

Posted

技术标签:

【中文标题】选择中的左连接与子查询的奇怪问题【英文标题】:Strange Problem With Left Join vs Subquery in Select 【发布时间】:2010-09-15 10:17:39 【问题描述】:

我有一个导致性能问题的 T-SQL 查询。它很笨重,但似乎导致问题的部分是一个简单的 LEFT JOIN。

这可以通过删除左连接并在选择中使用子查询来解决,但是这对我来说似乎并不令人满意,因为我不明白为什么一个快速工作而不是另一个工作。

涉及的数据不多,所有连接列上都有键/索引。我唯一想知道的另一件事是关于数据库的统计信息以及它们是否会影响性能。

例如(注意,这只是一个更复杂的查询的简化

SELECT A.1,A.2,B.3 FROM A LEFT JOIN B ON A.ID = B.ID ...

快速

SELECT A.1, A.2, (SELECT B.3 FROM B WHERE B.ID = A.ID) FROM A

【问题讨论】:

执行计划的主要区别是什么? 你不是真的使用序数来挑选列吗? 就像 hlgem 说的,第一个查询的其余部分是什么? 不,我没有使用序数,它是对更复杂查询的极大简化 【参考方案1】:

一般来说,子查询通常比左连接慢,所以肯定有其他事情发生。

首先显示整个查询,因为问题可能出在您使用 ... 表示的部分。

接下来检查您的执行计划,看看有什么不同。您是否绝对确定 id 列上有索引。 FK 约束不会自动创建索引。

两个查询是否返回相同的记录?一种可能更快,因为它不等同于另一种。

【讨论】:

我有理由确定问题不在 ... 因为 ... 已经投入生产一段时间了,它只是上面的部分发生了变化。 也有明确的索引并且已经验证查询返回相同的记录。 @AJM - 我不会这么快放弃 ... 部分。 SELECT 子句中的子查询将在处理完所有 FROM 子句元素后进行逻辑处理。当您将 LEFT OUTER JOIN 放在 FROM 子句中时,它会在所有 FROM 内容的中间进行处理。执行计划将显示这一点。【参考方案2】:

这两个查询可能不等价。如果您的子查询:

(SELECT B.3 FROM B WHERE B.ID = A.ID)

返回不止一行,你的左连接只会返回两行,但是你的子查询会因为“子查询返回不止一行”而崩溃。如果 B.ID 是唯一的,优化器是否知道它?你有唯一的约束或索引吗?

【讨论】:

以上是关于选择中的左连接与子查询的奇怪问题的主要内容,如果未能解决你的问题,请参考以下文章

如何将查询与子查询连接起来?

与子查询相比,为啥左外连接查询给出不同的结果?

Mysql 慢查询组与子查询连接

MSSQL之五 连接查询与子查询

SQL 内连接与子查询

左连接与子查询的性能问题以找出最新日期