MySQL回表

1.索引结构

1.1.B-Tree(B树)和B+Tree(B+树)

在这里插入图片描述
在这里插入图片描述

前面是B-Tree,后面是B+Tree,两者的区别在于:

  • B-Tree中,所有的节点都会带有指向具体记录的指针;B+Tree中只有叶子节点才会带有指向具体记录的指针;
  • B-Tree中,不同的叶子之间没有连在一起;B+Tree中所有的叶子节点通过指针连接在一起;
  • B-Tree中,可能在非叶子节点就拿到了指向具体记录的指针,搜索效率不稳定;B+Tree中,一定要到叶子节点才可以获取到指向具体记录的指针,搜索效率稳定;

基于上述几点分析,可以得出如下结论:

  • B+Tree中,由于非叶子节点不带有指向具体记录的指针,所以非叶子节点中可以存放更多的索引项,这样就可以有效降低树的高度,进而提高搜索的效率;

  • B+Tree中,叶子节点通过指针连接在一起,这样如果有范围扫描的需求,那么实现起来非常容易,而对于B-Tree,范围扫描则需要不停的在叶子节点和非叶子节点之间移动;

一棵B+Tree到底可以存放多少条数据呢?以主键索引的B+Tree为例(二级索引存储数据量的计算原理类似,但是叶子节点和非叶子节点上存储的数据格式略有差异),我们可以简单算一下:

①.计算机在存储数据的时候,最小的存储单元是扇区,一个扇区的大小是512字节,而文件系统(例如XFS,EXT4)最小单元是块,一个块的大小是4KB.INNODB引擎存储数据的时候,是以页为单位的,每个数据页的大小默认是16KB,即四个块;

②.假设数据库中一条记录是1KB,那么一个页就可以存放16条数据(叶子结点);对于非叶子节点存储的则是主键值+指针,在InnoDB中,一个指针的大小是6个字节,假设我们的主键是bigint,那么主键占8个字节(当然还有其他一些头信息也会占用字节我们这里就不考虑了),大概算一下:

16*1024/(8+6) = 1170

一个非叶子节点可以指向1170个页,那么一个三层的B+Tree可以存储的数据量为:

1170*1170*16 = 21902400 //可以存放2100万条数据

③.在InnoDB存储引擎中,B+Tree的高度一般为2-4层,这就可以满足千万级数据的存储,查找数据的时候,一次页的查找代表一次IO,那我们通过主键索引查询的时候,其实最多只需要2-4次IO操作就可以了;

2.两类索引

1.MySQL中的索引有很多种不同的分类方式,可以按照数据结构分,可以按照逻辑角度分,也可以按照物理存储分,其中按照物理存储方式,可以分为聚簇索引和非聚簇索引;

2.我们日常所说的主键索引,其实就是聚簇索引(Clustered Index);主键索引之外,其他的都是称之为非主键索引,非主键索引也被称为二级索引(Secondary Index),或者叫辅助索引;

3.对于主键索引和非主键索引,使用的数据结构都是B+Tree,唯一的区别在于叶子节点中存储的内容不同(最大的区别):

①.主键索引的叶子节点存储的是一行完整的数据;

②.非主键索引的叶子节点存储的则是主键值;

4.当我们进行查询的时候:

①.如果是通过主键索引来查询数据,例如"select * from user where id = 100",那么此时只需要搜索主键索引的B+Tree就可以找到数据;

②.如果是通过非主键索引来查询数据,例如"select * from user where username=‘zhangsan’",那么此时需要先搜索username这一列索引的B+Tree,搜索完成之后得到主键值,然后再去搜索主键索引的B+Tree,才可以取到一行完整的数据;

对于第二种查询方式而言,一共搜索了两棵B+Tree,第一次搜索非主键索引B+Tree,获取主键值之后再去搜索主键索引的B+Tree,这个过程就是所谓的回表;

3.一定会回表吗?

1.如果不使用主键索引就一定需要回表吗?

不一定!

2.如果查询的列本身就存在于索引中,那么即使使用二级索引,一样也是不需要回表的;

3.1.例子:

①.表结构如下:
在这里插入图片描述

如上图,uname和address字段组成一个复合索引,那么此时虽然这是一个二级索引,但是索引树的叶子节点中除了保存主键值,也保存了address和uname的值;

使用非主键字段查询数据,查看执行计划:
在这里插入图片描述

可以看到,此时使用到了uname作为查询条件,但是最后的extra的值为Using index,这就表示用到了索引覆盖扫描(覆盖索引),此时直接从索引中过滤不需要的记录并返回命中的结果,这一步是在MySQL服务层完成的,并不需要回表;

4.扩展: 为什么要在数据库中建议使用自增主键?

1>.自增主键往往占用空间比较小,int占4个字节,bigint占8个字节.由于二级索引的叶子节点存储的就是主键值,所以如果主键占用空间小,意味着二级索引的叶子节点将来占用的空间小(间接降低B+Tree的高度,一提高搜索效率);

2>.自增主键插入的时候比较快,直接插入即可,不会涉及到叶子节点分裂等问题(不需要挪动其他记录).而其他非自增主键插入的时候,可能要插入到两个已有的数据中间,就有可能导致叶子节点分裂等问题,插入效率低(要挪动其他记录);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值