【问题标题】:MySQL right join is order of magnitude faster for countingMySQL 右连接的计数速度要快一个数量级
【发布时间】:2020-09-24 20:13:53
【问题描述】:

有两个表,productssubmissions,都有大约 100 万条记录并且完全索引,我想根据条件计算元素。但是,即使计算连接的基本结果也很慢。

这些表具有 1-1 关系,submissions 具有 product_id 外键。请参阅以下 4 个查询:

select count(*)
from products P 
join submissions S on S.product_id=P.id 
# Takes 2 seconds

并解释该查询:

1   SIMPLE  S   index   submissions_product_id_foreign  submissions_product_id_foreign  4   NULL    776660  Using index
1   SIMPLE  P   eq_ref  PRIMARY PRIMARY 4   ma_prod.S.product_id    1   Using index

但是,运行以下查询:

select count(*)
from products P 
RIGHT join submissions S on S.product_id=P.id 

需要 300 毫秒。解释也不同:

1   SIMPLE  S   index   NULL    submissions_product_id_foreign  4   NULL    776662  Using index

我无法理解正在发生的事情。两个查询具有相同的结果并执行相同的连接,那么为什么要跳过 eq_ref 操作呢?此外,eq_ref 在外键上应该是超级快的。

【问题讨论】:

  • 请注意,没有人使用 RIGHT JOIN
  • 我只是想弄清楚发生了什么。您可以交换表并改为使用 LEFT JOIN,结果相同。
  • 好计划。 :-)。
  • 结果不同吗?如果是这样,您不能使用一种配方代替另一种。
  • 右外连接不太常见,但说它们从未使用过有些夸张。见quora.com/…

标签: mysql sql query-performance outer-join


【解决方案1】:

JOIN 的 MySQL 文档非常密集,但它说的一件有趣的事情是:

STRAIGHT_JOIN 与 JOIN 类似,只是左表总是 在右表之前阅读。这可以用于那些(少数)情况 连接优化器以次优方式处理表 顺序。

对于您的查询,RIGHT JOIN 说服优化器在左表之前读取右表,这样更好。获取每个提交并使用主键找到它所附带的单个产品 - 而不是获取每个产品并找到与其附带的多个提交,甚至使用索引。后一种方法显然会在表上迭代更多次。

我认为您基本上是在处理连接优化器中的错误或弱点,仅此而已。有时 MySQL 仍然需要出色的 DBA 帮助才能以更好的方式运行查询。

【讨论】:

    【解决方案2】:

    RIGHTLEFT JOINs 表示其中一张表(分别是左侧或右侧)的存在是可选的。

    通常,当您希望NULLs 丢失数据或发现丢失的行时,使用左或右。但你什么都没做。

    您是在询问有多少提交,而不是真正关心是否有匹配的product。并且优化器在设计查询执行时意识到product 没用,就把它扔掉了。

    所以,它更快。但可能有不同的COUNT(*)

    那么,您希望它“快速”还是“正确”?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 2012-11-11
      相关资源
      最近更新 更多