展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

常见索引和InnoDB的B+树索引的注意事项

常见索引

  • 聚簇索引
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式(所有的用户记录都存储在了叶子节点),也就是所谓的索引即数据,数据即索引

  • 其他特点
特点:
    1. 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
        页内的记录是按照主键的大小顺序排成一个单向链表
        各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表 
        存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表 
    2. B+树的 叶子节点 存储的是完整的用户记录。
        所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)

优点:
    数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
    聚簇索引对于主键的 排序查找 和 范围查找 速度非常快
    按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io操作

缺点:
    1.插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。
    因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
    2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新
    3.二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据
  • 二级索引(辅助索引、非聚簇索引)
聚簇索引只能在搜索条件是主键值时才能发挥作用,因为B+树中的数据都是按照主键进行排序的。那如果我们想以别的列作为搜索条件时,则是二级索引

  • 回表
根据这个以c2列大小排序的B+树只能确定我们要查找记录的主键值,所以如果我们想根据c2列的值查找到完整的用户记录的话,
仍然需要到 聚簇索引 中再查一遍,这个过程称为 回表 。也就是根据c2列的值查询一条完整的用户记录需要使用到 2 棵B+树
  • 联合索引
我们也可以同时以多个列的大小作为排序规则,也就是同时为多个列建立索引,比方说我们想让B+树按照 c2和c3列 的大小进行排序,这个包含两层含义:
    先把各个记录和页按照c2列进行排序。
    在记录的c2列相同的情况下,采用c3列进行排序
注意一点,以c2和c3列的大小为排序规则建立的B+树称为 联合索引 ,本质上也是一个二级索引。它的意思与分别为c2和c3列分别建立索引的表述是不同的,不同点如下:
    建立 联合索引 只会建立如上图一样的1棵B+树。
    为c2和c3列分别建立索引会分别以c2和c3列的大小为排序规则建立2棵B+树

InnoDB的B+树索引的注意事项

  1. 根页面位置万年不动,前边介绍B+树索引的时候,为了大家理解上的方便,先把存储用户记录的叶子节点都画出来,然后接着画存储目录项记录的内节点,实际上B+树的形成过程是这样的;一个B+树索引的根节点自诞生之日起,便不会再移动。这样只要我们对某个表建立一个索引,那么它的根节点的页号便会被记录到某个地方,然后凡是InnoDB存储引擎需要用到这个索引的时候,都会从那个固定的地方取出根节点的页号,从而来访问这个索引
每当为某个表创建一个B+树索引(聚簇索引不是人为创建的,默认就有)的时候,都会为这个索引创建一个根节点页面。最开始表中没有数据的时候,
每个B+树索引对应的根节点中既没有用户记录,也没有目录项记录。

随后向表中插入用户记录时,先把用户记录存储到这个根节点中。

当根节点中的可用空间用完时继续插入记录,此时会将根节点中的所有记录复制到一个新分配的页页a中,然后对页a进行页分裂的操作,得到另一个新页页b。这时新插入的记录根据键值(也就是聚簇索引中的主键值,二级索引中对应的索引列的值)的大小就会被分配到页a或者页b中,而根节点便升级为存储目录项记录的页
  1. 内节点中目录项记录的唯一性
保证在B+树的同一层内节点的目录项记录除页号这个字段以外是唯一的。所以对于二级索引的内节点的目录项记录的内容实际上是由三个部分构成的:
    索引列的值
    主键值
    页号
也就是我们把主键值也添加到二级索引内节点中的目录项记录了,这样就能保证B+树每一层节点中各条目录项记录除页号这个字段外是唯一的
  1. 一个页面最少存储2条记录
posted @ 2022-06-13 14:54  DogLeftover  阅读(27)  评论(0编辑  收藏  举报