B+树索引

Posted hangzhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B+树索引相关的知识,希望对你有一定的参考价值。

起因

通过InnoDB数据页结构可知所有数据页组成双链表结构,每个数据页中的记录按照主键大小组成单向链表,根据主键查询某条记录是从页目录通过二分法比较主键大小找到对应的槽,再遍历槽中的记录找到目标记录。但是主键查找有方法,那其他的列查找又怎么实现。如果通过从最小记录开始依次遍历,很明显很傻,所以引出了索引的概念。

过程

以InnoDB为例,假设某表采用compact为行格式存储记录,那么可知其中一条记录包含几个部分:record type,next record,各列的值,其他信息;主要看record type,0表示普通记录/1表示目录项记录/2表示最小记录/3表示最大记录,那么在数据页中一条记录的存在如下图:

技术图片

 

而添加数据记录涉及到页的过程如下:
  1. 插入一条记录到表中,而页10已经满了(页内容量很大,可以存好多记录)
  2. 那么分配一个新页28,(双向链表结构下,页号是不连续的,存储空间也不是挨着的)
  3. 这时发现页10最大主键为10,插入记录主键为8,但是为方便查找,下一页的最小主键必须大于上页的最大记录,所以需要移动主键为10的记录到页28,主键8的记录到页10.这个过程即页分裂,在新增页的时候发生。
  4. 因为页数很多,所以为更快定位记录所在页,将设一个目录(也称索引),数据页为目录项,目录项存储是一个连续存储空间,目录项包括数据页最小的主键值key和数据页页号,那么插叙某条记录时就可以用二分法从目录项中确定目标记录所在目录项,后遍历目录项即数据页中的记录
  5. 有两个问题:1.随着页数的增长目录项也随之增长,存储空间没有连续这么大的;2.如果删除某页中的全部记录,那么这个目录项随之删除。这就需要把该目录项后面的所有目录项都前移,比较麻烦
  6. 为解决上述问题,将新分配一个页专门存储目录项记录,这个页与普通记录存储页相似;查找目标记录的方式与之前的相同,依旧以二分法为主。
  7. 因存储目录项记录的页大小有限制,所以会有多个页来存储目录项;但是这些页在存储空间不是挨着的,那么怎么能快速定位目标记录存储在某个目录项记录的页,为了加速查找,可以将存储目录项的页再生成一个更高级的目录即大目录。

技术图片

一层一层下来就是一个树状即B+树,树由叶节点和根节点组成,最底下一层存储完整且实际的用户记录,称为叶节点;往上存放目录项的节点称为非叶节点或内节点,最顶上的称为根节点。那么查找目标记录同样也可采用二分查找法。

定义

聚簇索引

InnoDB会自动为我们创建聚簇索引,且聚簇索引就是数据的存储方式,核心在主键

  1. B+树的叶子节点存储的是完整的用户记录
  2. 页内记录/存放用户记录的页/存放目录项的页都是使用记录主键值的大小进行记录和排序的
二级索引

因聚簇索引的存储方式以主键大小排序,如果对其他列有查询要求,那么可以为其他列建索引B+树;但是和聚簇索引不同,这个B+树的叶子节点只存放查询列+主键的值,目录项存储列+页号+主键值;其他均以该列的大小顺序为主,排序方式和表用到的字符集有关,如果找到目标记录所在节点就会根据主键值去聚簇索引中查找完整的用户记录,即回表。

联合索引

以多个列的大小为排序顺序,即同时为多个列建索引,但只有一个B+树。记录项由列1,列2...,页号组成,叶子节点由列1,列2....和主键组成

todo

innoDB根页面不动,索引注意事项

myisam中索引方案

注:来自mysql是怎样运行的读数笔记

以上是关于B+树索引的主要内容,如果未能解决你的问题,请参考以下文章

索引是什么,索引的数据结构.B树,B+树

索引是什么,索引的数据结构.B树,B+树

索引是什么,索引的数据结构.B树,B+树

数据库常见索引解析(B树,B-树,B+树,B*树,位图索引,Hash索引)

B+树索引和哈希索引的区别

索引复习 B+树索引