MYSQL原理学习篇简记(四)

 

👏作者简介:大家好,我是小周同志,25届双非校招生Java选手,很高兴认识大家

📕学习出处:本文是学自小林coding (xiaolincoding.com) 网站的MYSQL图解篇

🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦

 

索引

什么是索引?

索引相当于数据的目录,能直接定位到数据。

索引的分类?

  • 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引
  • 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)
  • 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引
  • 按「字段个数」分类:单列索引、联合索引

按数据结构分类

B+tree索引

在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引:

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

其它索引都属于辅助索引(Secondary Index),也被称为二级索引或非聚簇索引。创建的主键索引和二级索引默认使用的是 B+Tree 索引

B+Tree 是一种多叉树,叶子节点才存放数据,非叶子节点只存放索引,而且每个节点里的数据是按主键顺序存放的。每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息,并且每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。

通过主键查询商品数据的过程

比如,我们执行了下面这条查询语句:

select * from product where id= 5;

这条语句使用了主键索引查询 id 号为 5 的商品。查询过程是这样的,B+Tree 会自顶向下逐层进行查找:

  • 将 5 与根节点的索引数据 (1,10,20) 比较,5 在 1 和 10 之间,所以根据 B+Tree的搜索逻辑,找到第二层的索引数据 (1,4,7);
  • 在第二层的索引数据 (1,4,7)中进行查找,因为 5 在 4 和 7 之间,所以找到第三层的索引数据(4,5,6);
  • 在叶子节点的索引数据(4,5,6)中进行查找,然后我们找到了索引值为 5 的行数据。

 B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。

我用 product_no 二级索引查询商品,如下查询语句:

select * from product where product_no = '0002';

会先检二级索引中的 B+Tree 的索引值(商品编码,product_no),找到对应的叶子节点,然后获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫「回表」,也就是说要查两个 B+Tree 才能查到数据

 

另外还有一个覆盖索引

select id from product where product_no = '0002';

通过查询 二级索引b+树 能得主键值也就是id的值,所以就不用再去查找 主键b+树 了 

覆盖索引 :只需要通过一个索引就能找到数据。

为什么 MySQL InnoDB 选择 B+tree 作为索引的数据结构?

1、B+Tree vs B Tree

B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据。所以 B+Tree 的单个节点的数据量更小,在相同的磁盘 I/O 次数下,就能查询更多的节点。

B+Tree 叶子节点采用的是双链表连接,适合 MySQL 中常见的基于范围的顺序查找,而 B 树不行。

2、B+Tree vs 二叉树

对于有 N 个叶子节点的 B+Tree,其搜索复杂度为O(logdN),其中 d 表示节点允许的最大子节点个数为 d 个。

在实际的应用当中, d 值是大于100的,这样就保证了,即使数据达到千万级别时,B+Tree 的高度依然维持在 3~4 层左右,也就是说一次数据查询操作只需要做 3~4 次的磁盘 I/O 操作就能查询到目标数据。

而二叉树的每个父节点的儿子节点个数只能是 2 个,意味着其搜索复杂度为 O(logN),这已经比 B+Tree 高出不少,因此二叉树检索到目标数据所经历的磁盘 I/O 次数要更多。

3、B+Tree vs Hash

Hash 在做等值查询的时候效率贼快,搜索复杂度为 O(1)。

但 Hash 表不适合做范围查询,它更适合做等值的查询,这也是 B+Tree 索引要比 Hash 表索引有着更广泛的适用场景的原因。

按存储类别分类

  • 主键索引的  B+Tree 的叶子节点存放的是实际数据;
  • 二级索引的  B+Tree 的叶子节点存放的是主键值(比如id是主键,那么就是存放的id值),而不是实际数据。

按字段特性分类

主键索引

主键索引就是建立在主键字段上的索引,通常在创建表的时候一起创建,一张表最多只有一个主键索引,索引列的值不允许有空值。

唯一索引

唯一索引建立在 UNIQUE 字段上的索引,一张表可以有多个唯一索引,索引列的值必须唯一,但是允许有空值。

普通索引

普通索引就是建立在普通字段上的索引,既不要求字段为主键,也不要求字段为 UNIQUE。

前缀索引

前缀索引是指对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引,前缀索引可以建立在字段类型为 char、 varchar、binary、varbinary 的列上。

按字段个数分类

从字段个数的角度来看,索引分为单列索引、联合索引(复合索引)。

单列索引

比如主键索引就是单列索引

联合索引

通过将多个字段组合成一个索引,该索引就被称为联合索引。

使用联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。

相关推荐

  1. MYSQL原理学习简记(五)

    2024-04-14 13:06:02       39 阅读
  2. MYSQL原理学习简记(三)

    2024-04-14 13:06:02       40 阅读
  3. 【面试题】MySQL(第)

    2024-04-14 13:06:02       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-14 13:06:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-14 13:06:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-14 13:06:02       87 阅读
  4. Python语言-面向对象

    2024-04-14 13:06:02       96 阅读

热门阅读

  1. python补充

    2024-04-14 13:06:02       34 阅读
  2. C++:基于范围的for循环

    2024-04-14 13:06:02       36 阅读
  3. CentOS 7源码包与RPM包软件安装详解

    2024-04-14 13:06:02       39 阅读
  4. Linux 忘记密码解决方法

    2024-04-14 13:06:02       40 阅读
  5. Django的APP应用更名(重命名)流程

    2024-04-14 13:06:02       39 阅读