image.png

一、B+树的引入

MySQL 中所有的数据都是存在表空间中(共享 or 独立)。
在 MySQL 中内存的数据以 页为基本单位(每页中存在多条记录数据)。

数据页(page) 与数据记录(row)通过链表的方式进行串联,逻辑图如下:
image.png
如上图,页与页之间通过链表互相关联,数据记录与数据记录之间同样通过链表进行关联。
并且串联的记录数据的主键从小到大进行排列。

页分裂:当插入一条新数据,数据主键在以后的数据中排在了上图的页c中记录2处,此时就需要将页c记录2处的数据往后移动,包括之后的所有页都需要进行数据移动,直到无需移动位置。
页分裂会造成性能问题,所以在进行数据插入时,应该遵循主键递增原则。

1.2、没有 B+树时的数据查询

在没有 B+树时进行数据查询,如:根据某个字段查询数据 “SELECT 字段 FROM 表明 WHERE 字段=xxx”

此时所能做的就是从id最小的值开始遍历整个表数据,然后匹配结果。也就是全表扫描。明显效率低下。

1.3、有 B+树时的数据查询(以聚簇索引为例)

image.png
如上述对页数据建立索引数据(类似于目录)。
MySQL 中数据默认使用主键id建立了索引,而无需用户显示定义。所以数据即索引索引即数据。
而默认通过主键创建的索引数据有如下特点:

  • 使用记录主键值进行记录和页的排序
  • B+树叶子节点存储了完整的用户记录

而满足以上两个特点的索引,又叫做聚簇索引。

在引入索引之后,根据主键id查询数据变得更简单(仅仅作用与主键id)

  • 根据主键值,确定叶子节点(每个叶子节点就是一个页的数据)
  • 根据页中的slot(槽)确定记录
  • 得到结果

二、索引

2.1、聚簇索引

InnoDB 在插入表数据时,默认以B+树的结构进行存储。
索引标识为记录主键id。

2.2、二级索引

聚簇索引是InnoDB 默认创建的B+树索引,但是聚簇索引只作用于主键id。对于其他字段无能为力。

这时候可以根据不同的字段,建立不同的 B+树索引树。这些索引也叫”二级索引“。

二级索引特点:(假设建立索引的字段为c)

  • 使用记录的 字段c 进行记录和页的排序
    页 据字段c进行排列形成单向链表
    页内数据 根据字段c进行排列形成双向链表
    同一层的页(树的同一层)同样按照字段c排序形成双向链表
  • B+树叶子节点不存储完整的记录,只存储 字段c + 主键值 这两个值
  • 目录项记录不再是 ”主键+页号“ ,而是”字段c+页号”

回表:二级索引中的节点只保存了“字段c + 主键” 两个列的值,所以在根据二级索引查完后,需要回表到聚簇索引中查找完整的用户记录。
这时候查找一条完整的记录需要使用到2棵 B+树。
不过如果此时我们需要的字段只有主键id,和字段c,就不需要进行回表,此时查询记录用到了 1棵B+树。

2.3、联合索引(也是二级索引)

二级索引使用单个字段建立B+树建立索引。
联合索引使用多个字段建立B+树索引树。
如:以 c1,c2 建立联合索引。对比:单独以 c1,c2 各自建立索引

  • 联合索引只建立一棵 B+ 树。单独的建立索引建立了两棵B+树。
  • 联合索引先按照c1 排序,相同的再按照 c2 排序。单独建立的索引根据各自的字段进行排序。