有一个综合指数是否有利于这样的事情:
SELECT * 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, a.bar, a.foo)
有一个综合指数是否有利于这样的事情:
SELECT * 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, a.bar, a.foo)
只有索引的前沿会被使用 ( a.id
),所以只有INNER JOIN
tob
会从索引中受益......所以索引中的附加列 (a.bar
和a.foo
) 在发布的示例查询中没有好处。
如果列不构成索引的最左前缀,则 MySQL 无法使用索引执行查找。假设您有
SELECT
此处显示的语句:SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; SELECT * FROM tbl_name WHERE col2=val2; SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
如果 上存在索引
(col1, col2, col3)
,则只有前两个查询使用该索引。第三和第四个查询确实涉及索引列,(col2)
但(col2, col3)
不是(col1, col2, col3)
.
当JOINing
(即INNER JOIN
, not 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 *
,这意味着您想要所有四个表中的所有列。如果情况并非如此,我们可以讨论另一种优化:“覆盖索引”。