MYSQL索引机制(InnoDB索引原理详解)

参考文章1
参考文章2

索引定义和一些概念:

索引(Index)是帮助MySQL高效获取数据的数据结构。

我们知道,数据库查询是数据库的最主要功能之一。但每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

索引一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作。所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。

在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的(例如树结构的选型和查找算法的实现),本文主要讨论InnoDB的索引实现方式。

数据存储特性决定快速查找必须要有索引:

当数据保存在磁盘类存储介质上时,它是作为数据块存放。这些数据块是被当作一个整体来访问的,这样可以保证操作的原子性。硬盘数据块存储结构类似于链表,都包含数据部分,以及一个指向下一个节点(或数据块)的指针,不需要连续存储。

所以-- 可以说数据库必须有索引,没有索引则检索过程变成了顺序查找,O(n)的时间复杂度几乎是不能忍受的。另一篇文章也会介绍mysql中如何建立索引。MYSQL索引建立(innoDB)

需要注意,某些操作会使得数据库放弃索引而进行全表扫描。导致引擎放弃使用索引而进行全表扫描的条件


B树(B-) 与B+树特性及存储原理:B树B+树的原理

数据结构:B树结构

图片.png

m 阶B树:

ceil--向上取整 , 以h高 m阶 B树为例

  1. 根结点只有一个,分支数量范围为[2,m];
  2. 分支结点,每个结点包含分支数范围为[ceil(m/2), m];
  3. 所有的叶结点都在同一层上;
  4. 有 k 棵子树的分支结点则存在 k-1个关键码,关键码按照递增次序进行排列;
  5. 每个结点关键字的数量范围为[ceil(m/2)-1, m-1]
插入(太多就分裂):

如果插入前该结点的关键字个数没有到达m-1个,那么直接插入即可;
如果插入前该结点的关键字个数已经到达m-1个,那么根据B树的性质显然无法满足,需要将其进行分裂。分裂的规则是该结点分成两半,将中间的关键字进行提升,加入到父亲结点中, 依次递归提升,分裂过后左右关键字也生成新的结点。

删除(不够就借):

如果该结点拥有关键字数量仍然满足B树性质,则不做任何处理;
如果该结点在删除关键字以后不满足B树的性质(关键字没有到达ceil(m/2)-1的数量),则需要向兄弟结点借关键字,这有分为兄弟结点的关键字数量是否足够的情况:

如果兄弟结点的关键字足够借给该结点,则过程为将父亲结点的关键字下移,兄弟结点的关键字上移;

如果兄弟结点的关键字在借出去以后也无法满足情况,那么我们可以将该结点合并到兄弟结点中,合并之后的子结点数量少了一个,则需要将父亲结点的关键字下放,如果父亲结点不满足性质,则向上回溯;


数据结构:B+树-MySQL普遍使用带有顺序访问指针的B+Tree实现其索引结构

B+树适合作为数据库的基础结构,也是因为适应计算机的内存-机械硬盘两层存储结构。


图片.png

m 阶B+树:

ceil--向上取整 , 以h高 m阶 B树为例

  1. 根结点只有一个,分支数量范围为[2,m];
  2. 非根分支结点,每个结点包含分支数范围和关键字的数量范围都为[ceil(m/2), m],关键码按照递增次序进行排列;
  3. 所有的叶结点都在同一层上;
插入

B+树的插入与B树的插入过程类似。不同的是B+树在叶结点上进行,如果叶结点中的关键码个数超过m,就必须分裂成关键码数目大致相同的两个结点,并保证上层结点中有这两个结点的最大关键码。

删除

B+树中的关键码在叶结点层删除后,其在上层的复本可以保留,作为一个”分解关键码”存在,如果因为删除而造成结点中关键码数小于ceil(m/2),其处理过程与B-树的处理一样。在此,我就不多做介绍了。


InnoDB索引原理:

索引实现:

MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

索引类别区分:

索引节点按照层级关系,有时又可以分为根节点和中间节点,其本质是一样的,都只包含下一层节点的入口值和入口指针;
叶子节点就不同了,它包含数据,这个数据可能是表中真实的数据行(聚集索引),也有可能是索引列值和行书签(辅助索引)
辅助索引和聚集索引

两点需要注意的:

不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。

由于B+Tree的特性,使用自增字段作为主键则是一个很好的选择。


MyISAM与InnoDB索引比较:

MyISAM的索引文件, 叶节点的data域存放的是数据记录的地址。

MyISAM主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。

而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。

因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)

你可能感兴趣的:(MYSQL索引机制(InnoDB索引原理详解))