MySQL索引

学习笔记是学习了 极客时间 - 《MySQL实战45讲》整理的笔记。

在 MySQL 中,索引是在存储引擎层实现的,所以并没有统一的索引标准,即不同存储引擎的索引的工作方式并不一样。由于目前主流的引擎是 InnoDB 存储引擎,因此我只记录InnoDB的索引擎模型。

B+ Tree

首先我们需要了解一下B+树

定义

  1. 每个结点最多有m-1个关键字。
  2. 根结点最少可以只有1个关键字。
  3. 非根结点至少有Math.ceil(m/2)-1个关键字。(向上去值)
  4. 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
  5. 所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。
  6. B+树包含2种类型的结点:内部结点(也称索引结点)和叶子结点。根结点本身即可以是内部结点,也可以是叶子结点。根结点的关键字个数最少可以只有1个。
  7. B+树与B树最大的不同是内部结点不保存数据,只用于索引,所有数据(或者说记录)都保存在叶子结点中。
  8. m阶B+树表示了内部结点最多有m-1个关键字(或者说内部结点最多有m个子树),阶数m同时限制了叶子结点最多存储m-1个记录。
  9. 内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
  10. 每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接。

参考链接

主键索引查找

如图所示:

MySQL索引_第1张图片
B+.jpg

我们可以看到这个就是一个典型的B+索引树。假设我们去搜索10这个数字,我们必须从根节点出发通过两段的查找,查找到所在的叶子节点,也就是保存数据的节点中,找到该值。

同时我们可以看到B+树的叶子节点的数据都是从大到小排列的,当我们查找一组数据大于10的数据时,我们会首先从根节点搜索,找到10的叶子节点,然后我们不必再从根节点去搜索大于10的叶子节点了,因为在每个叶子节点均有指向下一个叶子节点的指针,在这里也就是Q 。我们直接可以使用Q来进行大于10的数据的查找。

普通索引查找

MySQL索引_第2张图片
B+1.jpg

基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小,从性能和存储空间方面考量,自增主键往往是更合理的选择。

索引的搜索过程

之前的普通索引查找,我们经历了一次回表(回到主键索引树搜索的过程,我们称为回表)。

但是当我们执行

select * from T where k between 3 and 5 

这条语句时,会如何去查找索引呢。

MySQL索引_第3张图片
B+1.jpg

正常查找过程

  1. 在 k 索引树上找到 k=3 的记录,取得 ID = 300;
  2. 再到 ID 索引树查到 ID=300 对应的 R3;
  3. 在 k 索引树取下一个值 k=5,取得 ID=500;
  4. 再回到 ID 索引树查到 ID=500 对应的 R4;
  5. 在 k 索引树取下一个值 k=6,不满足条件,循环结束

这里由于我们使用的是 select *查询。

覆盖索引

如果执行的语句是 select ID from T where k between 3 and 5,这时只需要查 ID 的
值,而 ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表。也就是
说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为覆盖索引。

由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用
的性能优化手段。

最左前缀原则

B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。

为了直观地说明这个概念,我们用(name,age)这个联合索引来分析。索引项是按照索引定义里面出现的字段顺序排序的。

MySQL索引_第4张图片
索引1.jpg

可以看到,不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。

联合索引建立技巧

如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。比如 刚刚的 姓名和年龄的联合索引,有了这个索引,其实我们不需要再去建立一个 name索引了。

索引下推

上一段我们说到满足最左前缀原则的时候,最左前缀可以用于在索引中定位记录。但是如果不符合呢?

假如我们执行这条语句

select * from tuser where name like '张 %' and age=10

在MySQL 5.6 之后引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

MySQL索引_第5张图片
索引2.jpg

小结

了解Mysql基础的索引知识,更易于我们在业务上对数据表的优化。

你可能感兴趣的:(MySQL索引)