Mysql覆盖vs复合vs列索引

时间:2011-11-21 14:19:04

标签: mysql sql indexing covering-index composite-index

在以下查询中

SELECT  col1,col2
FROM    table1
WHERE   col3='value1'
  AND   col4='value2'

如果我在 col3 上有两个单独的索引,而在 col4 上有另一个索引,则在此查询中将使用哪一个?

我在某处读到,对于查询中的每个表,只使用一个索引。这是否意味着查询无法使用这两个索引?

其次,如果我同时使用 col3 col4 创建了一个复合索引,但在 WHERE中仅使用 col3

SELECT  col1,col2
FROM    table1
WHERE   col3='value1'

最后,在所有情况下使用覆盖索引是否更好? MYISAM和innodb存储引擎有什么不同?

4 个答案:

答案 0 :(得分:41)

覆盖索引与复合索引不同。

  

如果我在col3上有一个单独的索引,而在col4上有另一个索引,那么在这个查询中将使用哪一个?

基数最高的索引 MySQL会统计哪些索引具有哪些属性 将使用具有最大区分能力的索引(如MySQL的统计数据中所示)。

  

我在某处读到,对于查询中的每个表,只使用一个索引。这是否意味着查询无法使用这两个索引?

您可以使用子选择 或者甚至更好地使用包含col3和col4的复合索引。

  

其次,如果我同时使用col3和col4创建了一个复合索引,但在WHERE子句中只使用了col3,那么性能会更差吗?例如:

复合指数
正确的术语是compound索引,而不是复合词 仅使用复合索引的最左侧部分 因此,如果索引定义为

index myindex (col3, col4)  <<-- will work with your example.
index myindex (col4, col3)  <<-- will not work. 

请参阅:http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

请注意,如果选择最左侧的字段,则可以在where子句中不使用索引的那一部分。 想象一下,我们有一个复合指数

Myindex(col1,col2)

SELECT col1 FROM table1 WHERE col2 = 200  <<-- will use index
SELECT * FROM table1 where col2 = 200     <<-- will NOT use index.  

这样做的原因是第一个查询使用覆盖索引并对其进行扫描 第二个查询需要访问该表,因此扫描索引没有意义 这仅适用于InnoDB。

什么是覆盖指数
覆盖索引是指在查询中选择的所有字段都是covered索引的情况,在这种情况下,InnoDB(不是MyISAM)永远不会读取表中的数据,而只会使用索引中的数据,显着加快了选择。
请注意,在InnoDB中,主键包含在所有二级索引中,因此所有二级索引都是复合索引 这意味着如果您在InnoDB上运行以下查询:

SELECT indexed_field FROM table1 WHERE pk = something

MySQL将始终使用覆盖索引,不会访问实际的表。

答案 1 :(得分:5)

我赞成Johan's answer表示完整性,但我认为他对二级索引的陈述不正确和/或令人困惑;

Note that in InnoDB the primary key is included in all secondary indexes, 
so in a way all secondary indexes are compound indexes.

This means that if you run the following query on InnoDB:

SELECT indexed_field FROM table1 WHERE pk = something

MySQL will always use a covering index and will not access the actual table.

虽然我同意辅助索引中的主键是 INCLUDED ,但我不同意MySQL“将始终在此处指定的SELECT查询中使用覆盖索引”

要了解原因,请注意在这种情况下始终需要完整索引“扫描” 。这与“搜索”操作不同,而是对二级索引内容的100%扫描。这是因为主键的二级索引未订购;它按“indexed_field”排序(否则它不会用作索引!)。

鉴于后一个事实,在某些情况下,“寻找”主键,然后从“实际表”中提取indexed_field,而不是从二级索引中提取效率更高。

答案 2 :(得分:1)

这是一个我经常听到的问题,由于以下问题引起了很多混淆:

  • 多年来mySQL的差异。 多年来索引和多索引支持发生了变化(得到支持)

  • InnoDB / myISAM的差异 有一些关键的区别(下面),但我不相信多个索引是其中之一

MyISAM较老但经过验证。 MyISAM表中的数据分为三个不同的文件: - 表格格式,数据和索引 InnoDB比MyISAM相对更新,并且交易安全。 InnoDB还提供行锁定而不是表锁定,这增加了多用户并发性和性能。 InnoDB也有外键约束 由于其行锁定功能,InnoDB非常适合高负载环境。

为了确保事情,请务必使用explain_plan来分析查询执行情况。

答案 3 :(得分:0)

复合索引与复合索引不同。

  • 复合索引涵盖过滤器,连接和选择条件中的所有列。所有这些列都相应地存储在索引B树中的所有索引页上。
  • 复合索引涵盖B树中的所有过滤器和连接键列,但仅在叶页上保留选择列,因为它们不会被搜索,而只是被提取! 这节省了空间,因此创建了更少的索引页面,因此I / O更快。