我一直在这里查找有关此主题的一些文档:https://dev.mysql.com/doc/refman/5.7/en/left-join-optimization.html

但是我不明白下面的例子:


  联接优化器计算联接表的顺序。由LEFT JOIN或STRAIGHT_JOIN强制执行的表读取顺序可帮助联接优化器更快地完成其工作,因为要检查的表排列较少。这意味着,如果您执行以下类型的查询,则MySQL会对b进行全面扫描,因为LEFT JOIN会强制在d之前读取它:


SELECT * FROM a JOIN b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;


  在这种情况下,此修复方法与在FROM子句中列出a和b的顺序相反:


SELECT * FROM b JOIN a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;

为什么订单要进行优化? JOIN和LEFT_JOIN是否按一定顺序执行?

最佳答案

我怀疑第一句话不太正确。我已经看到LEFT JOIN变成了JOIN,然后表格以“错误”的顺序触摸了。

无论如何,不​​必担心优化器需要完成的工作。在成千上万的慢速JOINs中,我仅发现一种情况,即选择订单的成本很重要。这是对一个表进行多次联接的情况。 EAV模式的另一个缺点。无论如何,有一个简单的设置可以避免该问题。

LEFT/RIGHT/plain JOINs在语义上从左到右完成(无论优化器选择触摸表的顺序如何)。

如果您担心排序,则可以添加括号。例如:

FROM (a JOIN b ON ...) JOIN (c JOIN d ON ...) ON ...


如果使用的是“逗号”(FROM a,b...),请不要使用。但是,其优先级在很久以前就已更改。解决方法是添加括号,以使相同的SQL在更改前后的版本中均可使用。

不要使用LEFT,除非您需要它来缺少丢失的“正确”行而获得NULLs。它只是使读者感到困惑,以为您期望NULLs

08-06 00:36