子查询与连接

pal*_*sey 157 mysql sql performance database-design join

我重构了一个从另一家公司继承的应用程序的缓慢部分,以使用内部连接而不是子查询

WHERE id IN (SELECT id FROM ...)
Run Code Online (Sandbox Code Playgroud)

重构的查询运行速度提高了约100倍.(约50秒到约0.3)我预计会有所改善,但任何人都可以解释为什么它如此激烈?where子句中使用的列都已编入索引.SQL是否每行执行一次where子句中的查询?

更新 - 解释结果:

不同之处在于"where in in()"查询的第二部分 -

2   DEPENDENT SUBQUERY  submission_tags ref st_tag_id   st_tag_id   4   const   2966    Using where
Run Code Online (Sandbox Code Playgroud)

vs 1带连接的索引行:

    SIMPLE  s   eq_ref  PRIMARY PRIMARY 4   newsladder_production.st.submission_id  1   Using index
Run Code Online (Sandbox Code Playgroud)

Jef*_*dge 159

"相关子查询"(即,where条件依赖于从包含查询的行获得的值的那个)将对每一行执行一次.非相关子查询(where条件独立于包含查询的子查询)将在开头执行一次.SQL引擎自动进行区分.

但是,是的,解释计划会给你肮脏的细节.

  • 请注意,"DEPENDENT SUBQUERY"意味着与"相关子查询"完全相同. (3认同)

Skl*_*vvz 38

您正在为每一行运行子查询一次,而连接发生在索引上.

  • 这取决于 - 如果子查询以某种方式与外部查询(使用其数据)相关,则它将与每一行一起执行. (8认同)
  • 我不认为这是真的.SQL引擎只应运行子查询一次,并将结果用作列表. (5认同)
  • 在这种情况下可能是真的,但总的来说并非如此. (4认同)

小智 16

这是一个如何在MySQL 6.0中评估子查询的示例.

新的优化器会将这种子查询转换为连接.


小智 7

对每个版本运行解释计划,它会告诉您原因.


pfr*_*nza 6

在针对数据集运行查询之前,优化器会尝试以这样的方式组织查询,即它可以尽可能快地从结果集中删除尽可能多的元组(行).通常当您使用子查询(尤其是坏查询)时,在外部查询开始运行之前,无法从结果集中删除元组.

没有看到查询很难说原始的那么糟糕,但我的猜测是优化器无法做得更好.运行'explain'将显示用于检索数据的优化器方法.


Amy*_*y B 5

查看每个查询的查询计划。

where inJoin通常可以使用相同的执行计划来实现,因此它们之间的更改通常为零加速。


Cad*_*oux 5

优化器做得不太好。通常它们可以毫无差异地进行转换,并且优化器可以做到这一点。


Pet*_* II 5

这个问题有点笼统,所以这里是一个笼统的答案:

基本上,当 MySQL 有大量行需要排序时,查询需要更长的时间。

做这个:

对每个查询运行 EXPLAIN(先是 JOIN 查询,然后是子查询查询),然后在此处发布结果。

我认为看到 MySQL 对这些查询的解释的差异对于每个人来说都是一次学习经历。


Sha*_*awn 5

where 子查询必须为每个返回的行运行 1 个查询。内连接只需运行 1 个查询。