MySQL-- B+ 树



一、InnoDB 是如何存储数据的?

InnoDB 的数据是按「数据页」为单位来读写的

数据库的 I/O 操作的最小单位是页,InnoDB 数据页的默认大小是 16KB

单个数据页的结构及作用

多个数据页之间的逻辑连接(双向链表),不需要物理上的连续

InnoDB 给记录创建页目录 管理 -----> User Records(存储行记录内容)

数据页中的记录按照「主键」顺序组成单向链表,单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索。

页目录创建的过程如下:

  1. 将所有的记录划分成几个组,这些记录包括最小记录和最大记录,但不包括标记为“已删除”的记录;
  2. 每个记录组的最后一条记录就是组内最大的那条记录,并且最后一条记录的头信息中会存储该组一共有多少条记录,作为 n_owned 字段(上图中粉红色字段)
  3. 页目录用来存储每组最后一条记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量也被称之为槽(slot),每个槽相当于指针指向了不同组的最后一个记录

从图可以看到,页目录就是由多个槽组成的,槽相当于分组记录的索引。然后,因为记录是按照「主键值」从小到大排序的,所以我们通过槽查找记录时,可以使用二分法快速定位要查询的记录在哪个槽(哪个记录分组),定位到槽后,再遍历槽内的所有记录,找到对应的记录,无需从最小记录开始遍历整个页中的记录链表。

InnoDB 对每个分组中的记录条数都是有规定的,槽内的记录就只有几条:

  • 第一个分组中的记录只能有 1 条记录;
  • 最后一个分组中的记录条数范围只能在 1-8 条之间;
  • 剩下的分组中记录条数范围只能在 4-8 条之间。


二、B+ 树是如何进行查询的?

当我们需要存储大量的记录时,就需要多个数据页,这时我们就需要考虑如何建立合适的索引,才能方便定位记录所在的页

为了解决这个问题,InnoDB 采用了 B+ 树作为索引

InnoDB 里的 B+ 树中的每个节点都是一个数据页,结构示意图如下:

通过上图,我们看出 B+ 树的特点:

  • 只有叶子节点(最底层的节点)才存放了数据,非叶子节点(其他上层节)仅用来存放目录项作为索引。
  • 非叶子节点分为不同层次,通过分层来降低每一层的搜索量;
  • 所有节点按照索引键大小排序,构成一个双向链表,便于范围查询;


三、聚簇索引和二级索引

索引又可以分成聚簇索引和非聚簇索引(二级索引),它们区别就在于叶子节点存放的是什么数据:

  • 聚簇索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚簇索引的叶子节点;
  • 二级索引的叶子节点存放的是主键值,而不是实际数据。

因为表的数据都是存放在聚簇索引的叶子节点里,所以 InnoDB 存储引擎一定会为表创建一个聚簇索引,且由于数据在物理上只会保存一份,所以聚簇索引只能有一个。

InnoDB 在创建聚簇索引时,会根据不同的场景选择不同的列作为索引:

  • 如果有主键,默认会使用主键作为聚簇索引的索引键;
  • 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键;
  • 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键;

一张表只能有一个聚簇索引,那为了实现非主键字段的快速搜索,就引出了二级索引(非聚簇索引/辅助索引),它也是利用了 B+ 树的数据结构,但是二级索引的叶子节点存放的是主键值,不是实际数据。

二级索引的 B+ 树如下图,数据部分为主键值:

因此,如果某个查询语句使用了二级索引,但是查询的数据不是主键值,这时在二级索引找到主键值后,需要去聚簇索引中获得数据行,这个过程就叫作「回表」,也就是说要查两个 B+ 树才能查到数据。不过,当查询的数据是主键值时,因为只在二级索引就能查询到,不用再去聚簇索引查,这个过程就叫作「索引覆盖」,也就是只需要查一个 B+ 树就能找到数据。



四、参考

小林 coding

相关推荐

  1. MySQL数据结构BB+的区别

    2024-03-21 16:22:01       22 阅读
  2. BB+Mysql innodb的B+和其相关索引

    2024-03-21 16:22:01       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-21 16:22:01       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-21 16:22:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-21 16:22:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-21 16:22:01       20 阅读

热门阅读

  1. FDU 2018 | 1. 求众数

    2024-03-21 16:22:01       20 阅读
  2. el-table原始列表转换成树形数据

    2024-03-21 16:22:01       20 阅读
  3. blender记一下法线烘焙

    2024-03-21 16:22:01       22 阅读
  4. 在springboot中利用Redis实现延迟队列

    2024-03-21 16:22:01       21 阅读
  5. 【linux】grep 命令

    2024-03-21 16:22:01       21 阅读
  6. 【AI】计算机视觉是什么

    2024-03-21 16:22:01       24 阅读
  7. Linux运维_Bash脚本_编译安装PHP-7.4.28

    2024-03-21 16:22:01       22 阅读