【问题标题】:Should i avoid JOIN when MySQL not optimizing them?当 MySQL 不优化它们时,我应该避免 JOIN 吗?
【发布时间】:2018-10-26 06:05:10
【问题描述】:

在大学 SQL 课程关系数据库中,都是关于表之间的 JOINS 的。 所以我采用了一般的方法,首先做所有必要的 JOINS,然后选择数据,用 WHERE 过滤,必要时用 GROUP BY 过滤。这样代码和逻辑就很简单了。

但很多时候,当事情变得比单个 LEFT JOIN 更复杂时,我的性能会很差。

今天我只是重写了 JOIN 查询,执行时间为 600 秒 采用不同的方法: SELECT (SELECT ... WHERE ID = X.ID) FROM XSELECT ... WHERE Y IN (SELECT ...) 现在它在 0.0027 秒内完成。

我很沮丧,我在我加入的字段上使用索引,但是性能太差了...

【问题讨论】:

  • 真是个反问。连接很慢,如果可能,请避免它们。您不能在所有情况下都避免连接,某些任务需要连接。如果您需要一些查询优化方面的帮助,请提供更多详细信息。一切都很重要:查询、数据、索引、计划等。
  • 是的,我知道我的问题不太具体……但我相信有经验的人可以就此事给我很好的建议。实际上,有经验的人所说的“加入很慢,如果可能,请避免它们”是非常有用的。
  • 虽然没有JOIN 的重写仍然给出了最好的结果,但是通过使用EXPLAIN _query_ 我还发现我的索引是不完整的。我错误地忽略了对某个表的连接的索引,因为只有 40 条记录,我的错……之后,旧查询在 1 秒内完成。

标签: mysql performance join optimization


【解决方案1】:

LEFT JOIN可能,但并不总是强制先查看“左”表。

JOINs(但不是LEFT JOINs)加上一个接触一个表的WHERE,为优化器提供了一个强大、可靠的提示,可以先查看那个表。

JOIN,加上一个WHERE 涉及多个表——优化器有时会选择正确的“第一个”表,有时不会。

优化器通常从一个表中获取行(无论从哪个表开始都是最好的),然后执行 NLJ(嵌套循环连接)。这意味着一次进入下一个表的一行。这个“覆盖面”需要一个好的索引。

IN ( SELECT ... ),在版本中非常不理想。现在,它可能会变成一个“半连接”,比如EXIST ( SELECT ... ),并且效率很高。有时手动这样做是有益的。

“Explode-Implode”打击了很多人。这是有JOINGROUP BY 的地方。分组主要是为了内爆连接创建的大量行。有时,“派生”表可能是一个很好的优化。 (这是对查询的手动重新表述。)

通常用于聚合的LEFT JOIN 可以折叠成这样的形式:SELECT ..., ( SELECT SUM(foo) FROM ... ) AS foos, ...,从而减轻爆炸内爆。

不了解“复合”索引的好处可能是这个论坛上最常见的问题。

我要继续闲逛吗?我怀疑我是否涵盖了超过 1/4 的案例。所以,我同意@leftjoin。

这里有一些简单的提示:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

【讨论】:

  • 好的,所以“Explode-Implode”是已知的东西......我虽然优化器会首先自动按右表分组......很高兴知道它没有。
  • (我编造了“Explode-Implode”作为常见优化问题的术语。)
猜你喜欢
  • 1970-01-01
  • 2012-10-14
  • 2010-10-20
  • 2014-10-05
  • 1970-01-01
  • 2022-08-05
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
相关资源
最近更新 更多