写点什么

攻克 MySQL- 索引基础

作者:javaadu
  • 2022 年 2 月 26 日
  • 本文字数:1920 字

    阅读完需:约 6 分钟

攻克MySQL-索引基础

1. 基本概念

提到 MySQL,你脑海中浮现的概念是什么?锁、索引、慢 SQL、分库分表等等,这些概念在我们日常的开发工作中会经常用到,比如某个应用的监控和日志显示某个 SQL 的执行时间超过了 5 秒,并导致预定的功能没有正常执行,这时候我们再分析原因后,常常给到的解决方案是“给某几个字段加个索引吧”。通常来讲,80%的时候加个索引确实能解决问题,但是也有很多时候,我们明明加了索引但是查询效果依旧很慢,这就要求技术同学必须知其然更要知其所以然——彻底搞清楚索引的概念和底层的工作原理。


简单说,索引是存储引擎用于快速找到记录的一种数据结构。索引的出现就是为了提高数据库查询的效率,索引对于数据库的作用就像书的目录一样


2. 数据结构

2.1 有序数组

有序数组的查询时间复杂度是 O(Log(N)),同时也支持范围查询,但是它的弱点是维护成本很高,每次新插入一个数据,都要将要插入的位置之后的所有元素后移。


2.2 Hash 表

hash 表是数组的一种扩展,它的核心思想是:利用数组支持按照下标随机访问数据的特性,将要存储的数据的编号和数组的下标通过 hash 函数映射起来,即 index=hash(key),key 是要存储的数据的编号,index 是数组的下标,hash 是 hash 函数。hash 表这种数据结构的查询复杂度是 O(1),但是对于范围查询场景的支持并不好。


2.3 树

树也是一种经典的数据结构,基本的数据结构是二叉树,为了确保树的查询效率是 O(Log(N)),又推演出了平衡二叉树、红黑树等数据结构。在数据库存储引擎中使用二叉树是不够的,因为这会让树的高度很高,从而导致大量的磁盘访问,为了降低树的高度(减少磁盘访问的次数),我们就应该用 N 叉树。


3. InnoDB 的索引模型(B+树)

B+树的设计

B+ 树是一棵完全平衡的 m 阶多叉树。一个 4 层的 B+树就可以存储非常大的数据量,假设一个元素的大小是 0.01KB,一个 4K 的节点的内部可以存储 400 个元素,那么一个 4 层的 B+ 树最多能存储 400^4,也就是 256 亿个元素。


B+树的设计思路是充分考虑了磁盘+内存检索的常见的实际需要:(1)尽可能少的磁盘访问次数;(2)尽可能多得将数据在内存中访问。B+树的设计有下面几个特点:

  • 让一个节点的大小等于一个块的大小(操作系统读取磁盘数组的最小单位)。节点内存储的数据,不是一个元素,而是一个可以装 m 个元素的有序数组

  • 将所有的节点分为内部节点和叶子节点。尽管内部节点和叶子节点的数据结构是一样的,但存储的内容是不同的,内部节点只存储指针,叶子节点只存储数据,将索引和数据分离。

  • B+ 树还将所有叶子节点串成了有序的双向链表,这样一来,B+ 树就同时具备了良好的范围查询能力和灵活调整的能力了



B+树的操作

检索

B+树的检索过程是,先在根据树形查询找到叶子节点,然后再在叶子节点的数组中进行二分查找,整体的查询耗时依然是 O(Log(N))。

插入

B+树插入新的节点的时候,会先找到要插入的数据应该放入的叶子节点,如果发现叶子节点已经满了,这时候要先将叶子节点拆分为 2 个,然后再调整对应的父节点,如果发现父节点也需要调整,则持续调整,直到整个树处于稳定状态

删除

删除数据也类似,如果节点数组较满,直接删除;如果删除后数组有一半以上的空间为空,那为了提高节点的空间利用率,该节点需要将左右两边兄弟节点的元素转移过来。


4. 索引分类

存储方式

聚簇索引不是一种索引类型,而是一种数据存储方式,在 InnoDB 中使用的是聚簇索引,而在 MyISAM 中使用的是非聚簇索引。从下图中可以看出,InnoDB 的数据结构中,同时保存了索引的 key 和对应的数据,而在 MyISAM 中索引和数据则是分开的。



功能逻辑

主键索引 VS 二级索引

根据叶子节点存储的内容,可将索引区分为主键索引和二级索引,主键索引的叶子节点存放的是数据的行,二级索引的内容存放的是主键 ID。基于主键索引的查询,只需要差一次 B+树,而基于二级索引的查询则需要查 2 次,第一次查出主键 ID,第二次根据主键 ID 查询主键索引,这个查 2 次的过程,又称为“回表”。


普通索引 VS 唯一索引

根据是否有唯一性约束区分,主键索引一定是唯一索引,普通索引则没有唯一性的要求


单列索引 VS 组合索引

根据索引包含的字段个数区分,主键索引可以是单列索引或组合索引,看业务需求。唯一索引可以是单列索引或组合索引。


6. 面试问题

在工作中可能不会想这么多,但是最现实的情况来说,面试的时候对于这些底层技术原理的掌握,可以让面试官认可你的技术深度,因此广大开发同学还是要注重基础知识的掌握,基于本文的内容,我罗列了一些常见的面试问题,供大家思考。

  1. 索引的作用是什么?

  2. 为什么 Innodb 选择 B+树这种数据结构?

  3. 一些建表规范要求建表语句里一定要有自增主键,为什么这么要求?

  4. 聚集索引和非聚集索引的区别是什么?


7. 参考资料

  1. 《数据结构与算法之美》

  2. 《MySQL 实战》

  3. 《高性能 MySQL》

  4. 《SQL 必知必会》

  5. 《检索技术核心 20 讲》

发布于: 刚刚阅读数: 2
用户头像

javaadu

关注

功不唐捐 2017.09.10 加入

蚂蚁金服后端开发者,擅长java、spring、spring boot、jvm、分布式架构、软件设计等领域的技术分享,对于风控业务有一定的了解

评论

发布
暂无评论
攻克MySQL-索引基础