我一直在这里查找有关此主题的一些文档: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按某种顺序执行吗?
答案 0 :(得分:1)
我怀疑第一个引用不太正确。我看到LEFT JOIN
变成JOIN
,然后表格触及'错误'顺序。
无论如何,不要担心优化器需要做的工作。在成千上万的慢JOINs
中,我只确定了一个案例,其中选择订单的成本很重要。这是一个单个表的多个连接的情况; EAV架构的另一个缺点。无论如何,有一个简单的设置来避免这个问题。
LEFT/RIGHT/plain JOINs
从语义上从左到右完成(无论优化程序选择触摸表的顺序如何)。
如果您担心订购,可以添加括号。例如:
FROM (a JOIN b ON ...) JOIN (c JOIN d ON ...) ON ...
如果您使用的是“commajoin”(FROM a,b...
),请不要这样做。但是,它的优先权早就改变了。解决方法是添加parens,以便在更改之后和之前的版本中使用相同的SQL。
请勿使用LEFT
,除非您需要NULLs
来查找“右”行。它只是让读者误以为你期望NULLs
。
答案 1 :(得分:1)
这个例子在很多方面都是错误的,我不清楚它试图传达什么。为此道歉。我将向文档团队提交一个错误。
一些澄清: