当前位置: 首页 > 后端技术 > Java

MySQL的“后台”是什么?

时间:2023-04-01 21:44:41 Java

大家在面试的时候,有一个很常见的问题,就是数据库返回表。什么是退货单?为什么需要退货单?宋哥今天就来和大家聊聊这个话题。1、索引结构要理解这个问题,首先需要了解MySQL中索引存储的数据结构。其实很多朋友可能都听说过这个,B+Tree!B+树是什么?那你得先明白什么是B-Tree,看下图:前面是B-Tree,后面是B+Tree。两者的区别在于:在B-Tree中,所有节点都会有具体记录的Pointer;只有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,即四个块。基于这样的知识储备,我们可以大致计算出一个B+Tree可以存储多少数据。假设数据库中一条记录为1KB,那么一个页面可以存放16条数据(叶子节点);对于非叶子节点,存储主键值+指针。在InnoDB中,一个指针的大小是6个字Section,假设我们的主键是bigint,那么这个主键就占了8个字节,当然还有其他的头信息也会占字节,我们这里先不考虑,粗略算一下,小伙伴们可以知道:16*1024/(8+6)=1170表示一个非叶子节点可以指向1170页,那么一个三层的B+Tree可以存储的数据量为:1170*1170*16=21902400可以存储2100万条数据。在InnoDB存储引擎中,B+Tree的高度一般为2-4层,可以满足千万级数据的存储。在查找数据的时候,一次分页查找代表一次IO,所以我们通过主键索引查询的时候,其实最多只需要2-4次IO操作。我们先搞清楚这个B+Tree。2、两种索引众所周知,MySQL中索引有多种不同的分类方式,可以根据数据结构、逻辑角度或物理存储方式进行分类。其中,按照物理存储方式,又可分为聚集索引和非聚集索引。我们所说的主键索引其实就是聚集索引(ClusteredIndex);除了主键索引,其他的都称为非主键索引,非主键索引也称为二级索引(SecondaryIndex),或称为辅助索引。对于主键索引和非主键索引,使用的数据结构是B+Tree。唯一不同的是叶子节点存储的内容不同:主键索引的叶子节点存储的是完整的一行数据。非主键索引的叶子节点存储主键值。这是两者最大的区别。因此,当我们需要查询的时候:如果通过主键索引查询数据,比如select*fromuserwhereid=100,那么我们只需要搜索主键索引的B+Tree就可以找到数据。如果通过非主键索引查询数据,比如select*fromuserwhereusername='javaboy',那么需要先查找username列索引的B+Tree,之后得到主键的值查找完毕,再查找主键IndexedB+Tree,即可得到一行完整的数据。对于第二种查询方式,一共查找了两棵B+Trees。第一次搜索B+Tree得到主键值后,搜索主键索引的B+Tree。这个过程称为返回表。从上面的分析我们也可以看出,非主键索引查询需要扫描两颗B+Tree,而主键索引查询只需要扫描一颗B+Tree,所以如果条件允许,建议给优先查询按主键索引搜索。3.你会退回表格吗?那么是否需要返回没有主键索引的表呢?不确定!如果查询列本身存在于索引中,即使使用二级索引,也不需要回表。比如我有下表:uname和address字段组成了一个复合索引。这时候虽然这是二级索引,但是索引树的叶子节点不仅保存了主键值,还保存了地址值。我们看下面的分析:可以看到此时使用了uname索引,但是最后一个Extra的值为Usingindex,表示使用了索引覆盖扫描(coveringindex),不需要的是直接从索引中过滤。记录并返回命中结果,该步骤在MySQL服务器层完成,不需要返回表。4.展开基于第一节和第二节的分析,我们来看看为什么建议在数据库中使用自增主键。自增主键通常占用空间比较小,int占用4个字节,bigint占用8个字节。由于二级索引的叶子节点存放的是主键,如果主键占用的空间小,意味着以后二级索引的叶子节点占用的空间也小(间接降低了高度)B+树和提高搜索效率)。插入自增主键速度更快,直接插入即可,不会涉及到叶子节点分裂等问题(不需要移动其他记录);而其他非自增主键可能需要插入到两个已经存在的数据中间,可能会导致叶子节点分裂等问题,插入效率低(需要移动其他记录)。当然,这是基于技术讨论的。如果业务中不能使用自增主键,或者有其他需求导致不能使用自增主键,那么在满足新需求的同时,没有办法选择最佳实践。好了,今天的话题是returnform,现在大家明白returnform是什么了吧?