索引按照物理实现方式,索引可以分为 2 种:聚簇(聚集)和非聚簇(非聚集)索引。也可以把非聚集索引称为二级索引或者辅助索引。
一.聚簇索引
聚簇索引 并不是一种单独的索引类型,而是一种数据存储方式 (所有的用户记录都存储在了叶子节点),也就是所谓的索引即数据,数据即索引
。
特点:
1.使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
(1)页内的记录是按照主键的大小顺序排成一个单向链表 。
(2)各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表 。
(3)存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表 。
2.B+树的 叶子节点 存储的是完整的用户记录。
所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。
把具有这两种特性的B+树称为聚簇索引,所有完整的用户记录都存放在这个聚簇索引的叶子节点处。这种聚簇索引并不需要我们在MySQL语句中显式的使用INDEX语句去创建,InnoDB存储引擎会自动地创建聚簇索引。
优点:
数据访问更快 ,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
聚簇索引对于主键的 排序查找 和 范围查找 速度非常快
按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以 节省了大量的IO操作 。
缺点:
插入速度严重依赖于插入顺序 ,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,一般都会定义一个自增的ID列为主键
更新主键的代价很高 ,因为将会导致被更新的行移动。因此,对于InnoDB表,一般定义主键为不可更新
二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据
限制:
对于MysQL数据库目前只有InnoDB数据引擎支持聚簇索引,而MylSAM并不支持聚簇索引。
由于数据物理存储排序方式只能有一种,所以每个MySQL的表只能有一个聚簇索引。一般情况下就是该表的主键。
如果没有定义主键,InnoDB会选择非空的唯一索引代替。如果没有这样的索引,InnoDB会隐式的定义一个主键来作为聚簇索引。
为了充分利用聚簇索引的银簇的特性,所以InnoDB表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如UUID、MD5、HASH、字符串列作为主键无法保证数据的顺序增长
二.二级索引(非聚簇索引、辅助索引)
用c2列的大小作为数据页、页中记录的排序规则,再建一棵B+树,效果如下图所示:
这个B+树与上边介绍的聚簇索引有几处不同:
使用记录c2列的大小进行记录和页的排序,这包括三个方面的含义:
(1)页内的记录是按照c2列的大小顺序排成一个单向链表
(2)各个存放用户记录的页也是根据页中记录的c2列大小顺序排成一个双向链表
(3)存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的c2列大小顺序排成一个双向链表
(4)B+树的叶子节点存储的并不是完整的用户记录,而只是c2列+主键这两个列的值
(5)目录项记录中不再是主键+页号的搭配,而变成了c2列+页号的搭配
以查找c2列的值为4的记录为例,查找过程如下:
1.确定 目录项记录页
根据根页面 ,也就是页44,可以快速定位到目录项记录所在的页为页42(因为2<4< 9 )
2.通过目录项记录页确定用户记录真实所在的页
在页42中可以快速定位到实际存储用户记录的页,但是由于c2列并没有唯一性约束,所以c2列值为4的记录可能分布在多个数据页中,又因为2<4<=4,所以确定实际存储用户记录的页在页34和页35中
3.在真实存储用户记录的页中定位到具体的记录:
到页34和页35中定位到具体的记录
4.但是这个B+树的叶子节点中的记录只存储了c2和c1〔也就是主键)两个列,所以必须再根据主键值去聚簇索引中再查找一遍完整的用户记录。
概念:回表
根据这个以c2列大小排序的B+树只能确定要查找记录的主键值,所以如果想根据c2列的值查找到完整的用户记录的话,仍然需要到聚簇索引中再查一遍,这个过程称为回表。也就是根据c2列的值查询一条完整的用户记录需要使用到 2 棵B+树!