Mysql 复合索引中的独立Join子句
拥有一个综合指数是否有利于这样的事情:Mysql 复合索引中的独立Join子句,mysql,composite-index,Mysql,Composite Index,拥有一个综合指数是否有利于这样的事情: 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),因此只有到b的内部连接将受益于索引。。。因此,索引中的附加列(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
),因此只有到b
的内部连接将受益于索引。。。因此,索引中的附加列(a.bar
和a.foo
)对发布的示例查询没有好处
:
如果列不可用,MySQL无法使用索引执行查找
形成索引最左边的前缀。假设您有选择
声明如下:
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)
最左边的前缀
当连接
(即内部连接
,而不是左连接
)时,优化器将选择任何表作为“第一个”表。然后它将使用ON
子句移动到下一个表,并执行“NLJ”(嵌套循环联接)以到达第二个表。等等
通常,当存在WHERE
子句(或某些其他内容)时,将确定哪个表是“第一”。否则,优化器通常会选择最小的表
给定其中一个表上的WHERE
子句,它将查找要使用的“最佳”索引。这种索引可能在WHERE
子句中包含一个或多个列。两个索引(很少有例外)不会同时用于单个表
转到“下一个”表时,可能是on
子句中列上的索引决定了最佳索引。请注意,如果a.x=b.x和a.y=b.y上有,则需要使用复合索引(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
注意:每个表中可能已经有了主键(id)
,因此不需要添加索引(id)
您说的是选择*
,这意味着您需要所有四个表中的所有列。如果事实并非如此,我们可以讨论另一种优化:“覆盖索引”
更多讨论: