我一直在这里查找有关此主题的一些文档: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
。