-聚簇索引:将数据存储与索引放到一起,索引结构的叶子节点保存了行数据

-非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。

聚簇索引不一定是主键索引,而主键索引一定是聚簇索引。

可以理解成在聚簇索引上建立的索引,都是非聚簇索引(也称辅助索引)。因为一个表中只能有一个聚簇索引,其他都是非聚簇索引。 

辅助索引的叶子节点存储的不再是行的物理位置,而是主键值,辅助索引总需要二次查找(如下图,首先在自己的树上找,找ID,虚线也是找ID;然后第二次就是拿着这个ID去找)。

mysql 聚集索引sql mysql 聚集索引 非聚集索引_数据库

 这里抛出来一个问题,为什么不记得ID的地址,而要记录主键值ID,地址的话不是直接就能找到吗?

Reason:因为从增删改的角度,会导致叶子上地址发生变化(因为保存树平衡),而相对来说,主键值是不变的。

引擎上的区别:

InnoDB

使用的是聚簇索引,比如若使用“where id=14“的条件查找主键,则按照B+树的检索算法,即可查找到对应的叶节点,之后获得行数据。

若对Name列进行条件搜索,则需要两个步骤:①在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。②用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点获取整行数据。(重点在于通过其他键需要建立辅助索引

聚簇索引默认是主键,若表中无定义主键,InnoDB会选择一唯一且非空的索引代替。若无这样的索引,InnoDB会隐式定义一个主键(类似 oracle中的Rowld)作为聚簇索引。若已设了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除原主键,然后添加,最后恢复设置主键即可。

MyISAM

便用的是非聚簇索引,不同非聚簇索引的B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键, 辅助键索引IB+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。

使用聚簇索引的优势 :

每次使用辅助索引检索都要经过两次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?

-1.由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。(比如第一次主键ID访问访问到1,那么同一页的2,3,...也会被加载到缓存中,而非聚簇做不到。)

-2.辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化(重排);或者是我们需要查找的数据,在上一次I0读写的缓存中没有,需一次新的Io操作时,可避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储 空间大小。

聚簇索引需要注意什么?

当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。 ——建议使用int类型的自增方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,主键值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量。

为什么主键通常建议使用自增id

-聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么它会不断地调整数据的物理地址、分页,当然也有一些措施来减少这些操作,但无法彻底避免。但如果是自增的,只需一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

什么情况下无法利用索引呢?

1.查询语句中使用LIKE关键字

2.查询语句中使用多列索引,多列索引是在表的多个字段上创建一个常引,只有查询条件中使用了其中的第一个字段,索引才会被使用。

3.查询语句中使用OR关键字,查询语句只有OR关键字时,如果OR前后的两个条件的列是索引,那么查询中将使用索引。如果OR前后有一个条件的列不是索引,那么查询中将不使用索引。

本篇内容思想源于编程不良人课程的笔记。