6

有一个综合指数是否有利于这样的事情:

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)
4

2 回答 2

3

只有索引的前沿会被使用 ( a.id),所以只有INNER JOINtob会从索引中受益......所以索引中的附加列 (a.bara.foo) 在发布的示例查询中没有好处。

从 MySql 文档

如果列不构成索引的最左前缀,则 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).

于 2012-10-31T18:30:36.323 回答
0

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 *,这意味着您想要所有四个表中的所有列。如果情况并非如此,我们可以讨论另一种优化:“覆盖索引”。

更多讨论:http: //mysql.rjweb.org/doc.php/index_cookbook_mysql

于 2020-01-15T04:10:13.603 回答