复合指数是否有利于这样的事情:
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)
答案 0 :(得分:3)
仅使用索引的前沿(a.id
),因此只有INNER JOIN
到b
才能从索引中受益...所以索引中的其他列(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)
前缀。
答案 1 :(得分:0)
当JOINing
(即INNER JOIN
,而不是LEFT JOIN
)时,优化程序将选择表中的 any 作为“第一”表。然后它将使用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 *
,这意味着您需要所有四个表中的所有列。如果情况并非如此,我们可以讨论另一个优化:“覆盖索引”。