(1)前序
    聚簇索引就是innodb存储引擎默认给我们创建的一套基于主键的索引结构,而且我们表里的数据就是直接存放在聚簇索引里的,作为叶子节点的数据页。聚簇索引的搜索就是从聚簇索引的根节点 进行二分查找,一路找到对应的数据页里,基于页目录直接定位到主键对应的数据就可以了。
    但是如果想要对其他字段建立索引,甚至是基于多个字段建立联合索引,此时这个索引结构有时如何呢?
    93.jpg

    (2)对主键外的其他字段建立索引
    假设针对其他字段建立索引,比如name,age之类的字段,都是一样的道理,插入数据的时候,一方面把完整数据插入聚簇索引的叶子节点的数据页里去,同时维护好聚簇索引,另一方面会为 其他其他字段,重新建立一颗B+树。
    比如基于name字段建立一个索引,此时插入数据时重新建立一颗B+树,B+树的叶子节点也是数据页,但是这个数据页存放的仅仅是主键和name字段。注意这是独立于聚簇索引之外的另外一颗 索引B+树,严格说是name字段的索引B+树,所以在name字段的索引B+树,叶子节点仅存放主键和name字段的值,排序规则和之前的一样。也就是说,name字段的索引B+树里,叶子节点的数据页中的name 字段值都是按大小排序的,同时下一数据页里的name字段值都大于上一个数据页里的name字段值,这个整体的排序规则都跟聚簇索引按照主键的排序规则是一样的。

    1. 然后,name字段的索引B+树也会构建多层级的索引页,这个索引页存放的就是下一层的页号和最小name字段值,整体规则都是一样的。


    所以假设要根据name字段来搜索数据,搜索过程简直一样,都是从name字段的索引B+树里的根节点开始,一层一层的往下找,一直找到叶子节点里的数据页,定位到name字段对应的主键, 此时根据 select * from table where name=’xxxx’ 这样的语句,先根据name字段值在name字段的索引B+树里找,找到叶子节点也仅仅找到对应的主键值,而找不到这行数据完整的字段。 94.jpg

    1. 所以此时还需要进行"回表",这个**回表就是说还需要根据主键值**,再到聚簇索引里从根据点开始,一路找到叶子节点的数据页,定位到主键对应的数据行,此时就能把select * 要的全部字段值

    都拿出来了。因为我们根据name字段的索引B+树找到对应的主键之后,还要根据主键值,再到聚簇索引里找,所以一般把name字段这种普通字段的索引称之为二级索引,一级索引就是聚簇索引,这就是 普通字段的索引的运行原理。


    其实我们也可以把多个字段联合起来,建立联合索引,比如 name+age,运行原理也是一样的,单独建立B+树,叶子节点的数据页里存放id+name+age,然后默认按照name排序,name一样就按照 age排序,不同数据页之间的name+age值的排序也是如此。然后这个name+age的联合索引的B+树的索引页里,放的就是下层节点的页号和最小的name+age值,以此类推,所以当你根据name+age搜索的时候, 就会走name+age联合索引的B+树,搜索到主键,再根据主键到聚簇索引里去搜索。

    知识点:字符串类型的索引是怎么排序的? 根据ASCII码
    知识点:创建索引的时候则会去构建索引对应的索引页和叶子节点数据页。
    知识点:创建索引的过程很耗费时间,所以数据量较大的时候比较耗时,晚上低峰期处理。
    知识点:普通索引的叶子节点的数据页存储的就是普通索引字段和主键id,先根据name字段可以拿到一批id,然后再进行回表查询聚簇索引页。