聚簇索引和非聚簇索引是按照索引存储信息的物理位置来进行区分
聚簇索引
也称 Clustered Index。是指关系表记录的物理顺序与索引的逻辑顺序相同。由于一张表只能按照一种物理顺序存放,一张表最多也只能存在一个聚集索引。
一张表创建一定会创建仅且唯一的一颗聚簇索引树,并且row数据是挂载在非叶子节点上,若建表时有主键,则以该主键作为叶子节点索引值,若未有主键,则会默认创建uuid来代替。并且不能设置非主键为聚簇索引,而且一张表只能有一个主键,一个聚簇索引
辅助索引(非聚簇索引)
也叫 Secondary Index。指的是非叶子节点按照索引的键值顺序存放,叶子节点存放索引键值以及对应的主键键值
如图所示:叶子节点存放索引键值以及对应的主键键值
非聚集索引的存储结构与前面是一样的,不同的是在叶子结点的数据部分存的不再是具体的数据,而数据的聚集索引的key。
InnoDB 表是基于聚簇索引建立的,辅助索引会引用主键作为data域,存放叶节点之中。
这就导致辅助索引查找会进行两次检索:也就是当前索引树上的叶子节点存放
的数据不是查询所需的全部数据,而是主键索引的引用值,第二次通过主键检索到对应的数据,这就是回表
覆盖索引
如果某次查询的过程中,查询需要的数据在非聚簇索引中就可以得到,那么就没有必要回到聚簇索引查询行所有的数据,这种情况称为覆盖索引。我们可以把上面回表查询的SQL修改为:
select id from user_info where age = 5;
由于年龄索引树的叶子节点就包含了ID信息,所以InnoDB不需要回聚簇索引再次查询用户ID,而是直接将年龄索引树中的ID返回。
为什么要有页的概念呢?
所有的sql都是通过innodb引擎操纵操作系统去硬盘读数据,这样频繁的读取一行的数据性能是很差的,所以需要一次读取记录周围相邻的数据。
在创建mysql表的时候,那还是一页一页的申请空间吗?
那么这样的效率也太低了,而且意味着表的数据在磁盘中每一页的存储位置都是不连续的,这样随机IO的性能相比顺序IO性能较差,所以在申请资源时,需要抽象了一个区的概念,一个区可以容纳64页,而叶子节点和非叶子节点也要保证在区内是连续的,如图