mysql索引B+树<1>

135 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

MySQL官⽅对索引的定义是:索引(Index)是帮助MySQL⾼效获取数据的数据结构。

索引最形象的⽐喻就是图书的⽬录。注意只有在⼤量数据中查询时索引才显得有意义。

在MySQL中索引是在存储引擎层实现的,⽽不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。

一、索引的本质

索引的本质是一种排好序的数据结构。

二、索引的分类

1、按物理存储分类:聚集索引、⾮聚集索引(也叫⼆级索引、辅助索引)。

image.png

  • 聚集索引: 将数据存储与索引放到一块,索引结构的叶子节点保存了行数据,必须有且只有一个。
  • 二级索引: 将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键,可以存在多个。
  • 注意,一定会有聚集索引:
        1.默认主键为聚集索引;
        2.如果不存在主键,将使用第一个唯一(unique)索引作为聚集索引;
        3.上述都没有,则innodb会自动生成一个rowid作为隐藏的聚集索引。
  • 回表查询:

    是指先根据二级索引查到键值,然后通过键值回表查询聚集索引,从而获取行(row)数据。

image.png

2、按字段特性分类:主键索引(PRIMARY KEY)、唯⼀索引(UNIQUE)、普通索引(INDEX)、全⽂索引(FULLTEXT)。

  • 主键索引:针对于表中主键创建的索引,默认自动创建,只能有一个,primary。
  • 唯一索引:避免同一个表中某数据列中的值重复,可以有多个,unique。当你为某个字段创建唯一约束时,会自动创建唯一索引。
  • 常规索引:快速定位特定数据,可以有多个。
  • 全文索引:查找的是文本中的关键字,而不是比较索引中的值,可以有多个。

3、按字段个数分类:单列索引、联合索引(也叫复合索引、组合索引)。

  • 单列索引:单个字段构建的索引。
  • 联合索引:多个字段组合的联合索引。

4、按数据结构分类:B+tree索引、Hash索引、二叉树、。

Hash 索引:

Hash 索引是比较常见的一种索引,他的单条记录查询的效率很高,时间复杂度为1。但是,Hash索引并不是最常用的数据库索引类型,尤其是我们常用的Mysql Innodb引擎就是不支持hash索引的。主要有以下原因: Hash索引适合精确查找,但是范围查找不适合

二叉树:

常见的索引使用的数据结构是树结构,首先我们来介绍下最经典的二叉树。

image.png

先来介绍下二叉树的特点:

    1. 二叉树的时间复杂度为 O(n);
    1. 一个节点只能有两个子节点。即度不超过2;
    1. 左子节点 小于 本节点,右子节点 大于 本节点;
    1. 极端情况下二叉树会链化成单一链表;

image.png

  1. 二叉树中,有一种特殊的结构——平衡二叉树,

    平衡二叉树的特点:

    根节点会随着数据的改变而变更;
    
    数据量越多,遍历次数越多,IO次数就越多,就越慢(磁盘的IO由树高决定)
    

B树(二三树)

B 树大概是这样子的:

image.png

从B树的结构图中可以看到每个节点中不仅包含数据的 key 值,还有 data 值。

而每页的存储空间是有限的,如果 data 比较大,会导致每个节点的 key 存储的较少,当数据量较大的时候,同样会导致B树很深,从而增加了磁盘 IO 的次数,进而影响查询效率。

B+树

MySQL 中最常用的索引的数据结构是 B+ 树,他有以下特点:

  1. 在 B+ 树中,所有数据记录节点都是按照键值的大小存放在同一层的叶子节点上,而非叶子结点只存储key的信息,这样可以大大减少每个节点的存储的key的数量,降低B+ 树的高度
  2. B+ 树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针;
  3. B+ 树的层级更少:相较于 B 树 B+ 每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快
  4. B+ 树查询速度更稳定:B+ 所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同所以查询速度要比B树更稳定;
  5. B+ 树天然具备排序功能:B+ 树所有的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。
  6. B+ 树全节点遍历更快:B+ 树遍历整棵树只需要遍历所有的叶子节点即可,而不需要像 B 树一样需要对每一层进行遍历,这有利于数据库做全表扫描

好了说了这么多的 B+ 树的特点,我们来张图看看 B+ 树到底长什么样子:

image.png

上面的数据页就是实际存放数据页的地方,且数据页之间是通过双向链表进行连接的。

MySQL 在存储数据的时候是以数据页为最小单位的,且数据在数据页中的存储是连续的,数据页中的数据是按照主键排序的(没有主键是由 MySQL自己维护的 ROW_ID 来排序的),数据页和数据页之间是通过双向链表来关联的,数据与数据时间是通过单向链表来关联的。

三、聚簇索引、覆盖索引和非主键索引

聚簇索引 MySQL基于主键索引结构创建的B+树,也是二叉搜索树的一种,数据仅仅存储在叶子节点,这种集索引页+数据页组成的组成的B+树就是**聚簇索引*。

覆盖索引(covering index),MySQL只需要通过索引就可以返回查询所需要的数据,而不必在查到索引之后再去回表查询数据,所以相当快!!但是同时也要求所查询的字段必须被索引所覆盖到,在Explain的时候,输出的Extra信息中如果有“Using Index”,就表示这条查询使用了覆盖索引。

非主键索引一般都是联合索引,在维护 B+ 树的时候,会根据联合索引的字段依次去判断,假设联合索引为:a + b + c,那么 MySQL 在维护该索引的 B+ 树的时候,首先会根据 a 进行排序,a 相同的话会根据第二个 b 排序,如果 b 也一样,那么就会根据 c 去排序,如果 c 也一样,那么就会根据主键字段值去排序,且对于非主键索引,MySQL 在维护 B+ 树的时候,仅仅是维护索引字段和主键字段

参考学习网址:

blog.csdn.net/weixin_4474…