何时使用SQL子查询与标准连接?

Bra*_*ark 36 sql join subquery

我正在努力重写一些写得不好的SQL查询,他们过度使用子查询.我正在寻找有关子查询使用的最佳实践.

任何帮助,将不胜感激.

Mar*_*ers 52

子查询通常很好,除非它们是从属子查询(也称为相关子查询).如果您只使用独立子查询并且他们使用适当的索引,那么它们应该快速运行.如果您有从属子查询,则可能会遇到性能问题,因为依赖子查询通常需要为外部查询中的每一行运行一次.因此,如果外部查询有1000行,则子查询将运行1000次.另一方面,独立子查询通常只需要评估一次.

如果您不确定子查询是依赖的还是独立的,这是一个经验法则 - 如果您可以使用子查询,将其从上下文中删除,运行它,并获得结果集,那么它就是一个independent subquery.

如果你得到语法错误,因为它引用了子查询之外的一些表,那么它是a dependent subquery.

一般规则当然有一些例外.例如:

  • 许多优化器可以使用从属子查询并找到一种方法来有效地将其作为JOIN运行.例如,NOT EXISTS查询可能会导致ANTI JOIN查询计划,因此它不一定比使用JOIN编写查询慢.
  • MySQL有一个错误,其中IN表达式中的独立子查询被错误地标识为从属子查询,因此使用了次优的查询计划.这显然是在MySQL的最新版本中修复的.

如果性能是一个问题,那么衡量您的具体查询,看看哪种方法最适合您.

  • "许多优化器可以采用依赖子查询并找到一种有效运行它的方法" - 我同意这个说法,它否定了你的整个论点,即"相关的子查询是坏的,除非它们不坏". (3认同)

Ric*_*iwi 6

这里没有银弹.每个用法都必须独立评估.在某些情况下,相关子查询效率很低,下面这个更好地写为JOIN

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u
Run Code Online (Sandbox Code Playgroud)

另一方面,EXISTS和NOT EXISTS查询将胜过JOIN.

select ...
where NOT EXISTS (.....)
Run Code Online (Sandbox Code Playgroud)

通常比快

select ...
FROM A LEFT JOIN B
where B.ID is null
Run Code Online (Sandbox Code Playgroud)

然而,即使这些概括对于任何特定的模式和数据分布也是不正确的.

  • ......和RDBMS :-) (3认同)