MySQL的Innodb存储引擎的索引分为聚集索引和非聚集索引两大类,不同的索引会带来不同的查询效率,根据自己的业务设计正确的索引,才能最大程度提高应用体验。

基本概念

聚集索引(Clustered Index)

索引的键值决定了表中相应行的物理顺序,类似字典,按照拼音进行排列。
聚集索引对于经常需要范围查询的列特别有效,找到一个值后,可以同时查找到物理相邻的数据,减少磁盘IO,增加拆线呢效率。

非聚集索引(Nonclustered indexes)

非聚集索引索引项顺序存储,但索引项对应的内容却是随机存储的,叶子节点是索引节点,然后指针指向了实际存储的顺序。

例子

建表:

1
2
3
4
5
6
7
8
9
10
11
create table student (

`id` INT UNSIGNED AUTO_INCREMENT,

`name` VARCHAR(255),

PRIMARY KEY(`id`),

KEY(`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

该表中主键id是该表的聚集索引、name为非聚集索引;表中的每行数据都是按照聚集索引id排序存储的;比如要查找name=’Arla’和name=’Arle’的两个同学,他们在name索引表中位置可能是相邻的,但是实际存储位置可能差的很远。name索引表节点按照name排序,检索的是每一行数据的主键。聚集索引表按照主键id排序,检索的是每一行数据的真实内容。

也就是说查询name=’Arle’的记录时,首相通过name索引表查找到Arle的主键id(可能有多个主键id,因为有重名的同学),再根据主键id的聚集索引找到相应的行记录;

聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引,如果还是没有的话,就采用Innodb存储引擎为每行数据内置的6字节ROWID作为聚集索引。

每张表只有一个聚集索引,因为聚集索引在精确查找和范围查找方面良好的性能表现(相比于普通索引和全表扫描),聚集索引就显得弥足珍贵,聚集索引选择还是要慎重的(一般不会让没有语义的自增id充当聚集索引)。

(1)select * from student where id >5000 and id <20000;

(2)select * from student where name > ‘Alie’ and name < ‘John’;

第一条SQL语句根据id进行范围查询,因为(5000, 20000)范围内的记录在磁盘上按顺序存储,顺序读取磁盘很快就能读到这批数据。
第二条SQL语句查询(’Alie’, ‘John’)范围内的记录,主键id分布可能是离散的1,100,20001,5000…..;增加了随机读取数据页几率;所以普通索引的范围查询效率被聚集索引甩开几条街都不止;非聚集索引的精确查询效率还是可以的,比聚集索引查询只增加了一次IO开销。