从头带你捋一遍 MySQL 索引结构( 四 )


B+树的优势

由于叶子节点上存放了所有的数据,并且有指针相连,每个叶子节点在逻辑上是相连的,所以对于范围查找比较友好 。
 
B+树的所有数据都在叶子节点上,所以B+树的查询效率稳定,一般都是查询3次 。
 
B+树有利于数据库的扫描 。
 
B+树有利于磁盘的IO,因为他的层高基本不会因为数据扩大而增高(三层树结构大概可以存放两千万数据量 。
页的完整结构说完了页的概念和页是如何一步一步地组合称为B+树的结构之后,相信大家对于页都有了一个比较清楚的认知,所以这里就要开始说说官方概念了
基于我们上文所说的,给出一个完整的页结构,也算是对上文中自己理解页结构的一种补充 。
从头带你捋一遍 MySQL 索引结构

文章插图
 
上图为 Page 数据结构,File Header 字段用于记录 Page 的头信息,其中比较重要的是 FIL_PAGE_PREV 和 FIL_PAGE_NEXT 字段,通过这两个字段,我们可以找到该页的上一页和下一页,实际上所有页通过两个字段可以形成一条双向链表 。
Page Header 字段用于记录 Page 的状态信息 。接下来的 Infimum 和 Supremum 是两个伪行记录,Infimum(下确界)记录比该页中任何主键值都要小的值,Supremum (上确界)记录比该页中任何主键值都要大的值,这个伪记录分别构成了页中记录的边界 。
 
User Records 中存放的是实际的数据行记录,具体的行记录结构将在本文的第二节中详细介绍 。Free Space 中存放的是空闲空间,被删除的行记录会被记录成空闲空间 。Page Directory 记录着与二叉查找相关的信息 。File Trailer 存储用于检测数据完整性的校验和等数据 。
引用来源:https://www.cnblogs.com/bdsir/p/8745553.html
基于B+树聊聊MySQL的其它知识点看到这里,我们已经了解了MySQL从单条数据开始,到通过页来减少磁盘IO次数,并且在页中实现了页目录来优化页中的查询效率,然后使用多页模式来存储大量的数据,最终使用目录页来实现多页模式的查询效率并形成我们口中的索引结构——B+树 。既然说到这里了,那我们就来聊聊MySQL的其他知识点 。
聚簇索引和非聚簇索引关于聚簇索引和非聚簇索引在[令人脱发的数据库底层设计]这篇文章中已经有了详细的介绍,这里简单地说说
所谓聚簇索引,就是将索引和数据放到一起,找到索引也就找到了数据,我们刚才看到的B+树索引就是一种聚簇索引,而非聚簇索引就是将数据和索引分开,查找时需要先查找到索引,然后通过索引回表找到相应的数据 。InnoDB有且只有一个聚簇索引,而MyISAM中都是非聚簇索引 。
联合索引的最左前缀匹配原则在MySQL数据库中不仅可以对某一列建立索引,还可以对多列建立一个联合索引,而联合索引存在一个最左前缀匹配原则的概念,如果基于B+树来理解这个最左前缀匹配原则,相对来说就会容易很很多了 。
首先我们基于文首的这张表建立一个联合索引:
createindexidx_objonuser(ageasc,heightasc,weightasc)我们已经了解了索引的数据结构是一颗B+树,也了解了B+树优化查询效率的其中一个因素就是对数据进行了排序,那么我们在创建idx_obj这个索引的时候,也就相当于创建了一颗B+树索引,而这个索引就是依据联合索引的成员来进行排序,这里是age,height,weight 。
看过我之前那篇博客的同学知道,InnoDB中只要有主键被定义,那么主键列被作为一个聚簇索引,而其它索引都将被作为非聚簇索引,所以自然而然的,这个索引就会是一个非聚簇索引 。
所以根据这些我们可以得出结论:
  • idx_obj这个索引会根据age,height,weight进行排序
  • idx_obj这个索引是一个非聚簇索引,查询时需要回表
根据这两个结论,首先需要了解的就是,如何排序?
单列排序很简单,比大小嘛,谁都会,但是多列排序是基于什么原则的呢(重点)?
实际上在MySQL中,联合索引的排序有这么一个原则,从左往右依次比较大小,就拿刚才建立的索引举例子,他会先去比较age的大小,如果age的大小相同,那么比较height的大小,如果height也无法比较大小,那么就比较weight的大小,最终对这个索引进行排序 。
那么根据这个排序我们也可以画出一个B+树,这里就不像上文画的那么详细了,简化一下:
数据:
从头带你捋一遍 MySQL 索引结构


推荐阅读