当JOINing(即INNER JOIN,而不是LEFT JOIN)时,优化器将选择任何表作为“第一个”表。然后它将使用ON 子句移动到下一个表并执行“NLJ”(嵌套循环连接)以进入第二个表。等等。
通常,当有 WHERE 子句(或某些其他内容)时,它将确定哪个表是“第一个”。否则,优化器通常会选择最小的表。
给定一张表上的WHERE 子句,它将寻找“最佳”INDEX 来使用。这样的索引很可能在WHERE 子句中涉及一个或多个列。两个索引不会(极少数例外)同时用于单个表。
当移动到“下一个”表时,可能ON 子句中的列上的索引确定最佳索引。请注意,如果您有ON a.x=b.x AND a.y=b.y,则需要复合INDEX(x,y)(任意顺序)。
回到不决定从哪个表“开始”的情况......优化器将为该表尝试各种顺序。对于每个不同的排序,都有一组不同的索引。
为此
FROM a
INNER JOIN b ON(a.id=b.id)
INNER JOIN c ON(a.bar=c.id)
INNER JOIN d ON(a.foo=d.id)
这些是最优的,但我们不一定能预测会使用哪个:
a: (id) -- if coming from b
a: (bar) -- if coming from c
a: (foo) -- if coming from d
b: (id) -- if coming from b
c: (id) -- if coming from a
d: (id) -- if coming from a
注意:您可能已经在每个表中添加了PRIMARY KEY(id),因此无需添加INDEX(id)。
你说SELECT *,意思是你想要所有四个表中的所有列。如果情况并非如此,我们可以讨论另一种优化:“覆盖索引”。
更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql