四、mysql——InnoDB中区和段的概念

提示:一个页的大小默认是16kb,一个表空间的大小是很大的,里面包含了非常多的页,因此为了更好的管理这些页,就引入了区的概念,64个连续的页就是区,因此区默认大小是1mb。


前言


一、区的概念

1.1区的概念

一个页的大小默认是16kb,一个表空间的大小是很大的,里面包含了非常多的页,因此为了更好的管理这些页,就引入了区的概念,64个连续的页就是区,因此区默认大小是1mb。

1.2 为什么引入区

首先一定要明确的是完整的数据是存储在B+树的叶子节点的,你也可以认为对于InnoDB类型的表,数据就是逻辑存储结构节是这个表(因为InnoDB一定有主键,还记得前面对于InnoDB类型的表主键的生成策略吧,如果忘记了可以回到B+树这个章节看看)。无论怎样着我们的完整数据是存储在聚簇索引的叶子节点的,二级索引的话,叶子中存储表中的索引列和主键列。无论是二级索引还是聚簇索引,页与页之间是按照索引列升序形成的双向链表(不考虑8.0的降序索引),但是这些页在磁盘上的存储,不一定是连续的,也就是我们在读取页中数据的时候,其实整体采用的是随机IO,个别页与页之间可能存储是连续的,采用是顺序IO,区的定义是把64个连续的页定义为区,就是在磁盘中划分64个16kb连续的空间,那在读这64个页时就是连续的了,进而降低了随机IO的次数,提高查询效率。

注意:
在表中数据量很大的时候,为某个索引分配空间的时候,就会按照区为单位分配空间,而不再按页(一开始按页,当连续分配32个页的时候,就会按照区来分配空间),甚至在表中数据量特别大时,还可能一次分配多个连续的区。


二、段

InnoDB对B+树的叶子节点和非叶子节点进行了区别对待,也就是说叶子节点有自己独立的区,非叶子节点也有自己独立的区。存放区的结合就叫做段,InnoDB把所以分为两个段:叶子节点段和非叶子节点段。


三、碎片区

默认一个InnoDB只有聚簇索引(不考录二级索引),上面说一个索引分两个段,而段是以区为单位申请存储空间的,一个区默认占用1mb存储空间。那一个索引最小也得2mb,如果数据量很小,就几条记录,但是我上来就占用2mb的存储空间合适嘛?现在的问题,在于我们之前说的区都是非常纯粹的,也就是一个区被整个分配给某一个段,或者说区中的所有数据都是都是为了存储同一段数据而存在的。即使段的数据填不满区中所有的页面,剩下的页面也不能挪为他用。现在考察【以完整的区为单位分配给某个段时,对于数据量较小的表来说太浪费存储空间】这种为情况,InnoDB提出了碎片区的概念。

1、一个碎片区中,并不是所有的页属于段A,有些页属于段B,有些页甚至不属于任何段。
2、碎片区直属于表空间,并不属于任何一个段(碎片区里面的页可能属于某个段)。
3、为某个段分配存储空间的策略是这样的:
①在刚开始向表中插入数据时,段是某个碎片区以单个页面为单位来分配存储空间的。
②当某个段已经占用了32个碎片区页面后,就会以完整的区为单位分配存储空间(原先占用的碎片区页面并不会被复制到新申请的完整的区中)

注意:
碎片区可以理解为,某两个段中数据很少的时候,加入就一条记录,我直接放一个段中不合适,太浪费空间了,索性InnoDB直接划一个"区"(加上引号,这个不是一个我们传统意义上的区)出来,本来存放在段A中的一条记录,你就直接占用区中一个页,本来属于段B的一条数据,你也别自己占用一个段了,你也放这个"区"里。那我申请的这个"区",段A和段B的数据都有,那我显然不能说属于任何一个段,那就直接共用起来,我属于表空间吧。。。。为什么说“碎片”呢?因为传统意义上的区中页都属于同一个段,但是我这个“区”既可能有段A的页,也可能有B的等等,所以也就叫碎片区了。

四、总结

1、区简单的理解为64个连续的页
2、我们之前方便理解段的概念,把段说成是区的集合,但是在说了碎片区之后,更精确地说,段是某些零散的页面(来自碎片区的)和一些完整的区的集合。
3、碎片区是解决空间浪费问题提出的,直属于表空间。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 确实,MySQL的varchar类型在InnoDB存储引擎中的存储结构比较复杂。在InnoDB中,每个记录都被存储为一个B+树节点,每个节点都有一个固定大小的页,通常为16KB。 当一个varchar类型的列被插入到InnoDB表中时,它会被拆分成两个部分:一个是实际的数据,另一个是长度信息。长度信息会被存储在记录头中,而实际的数据会被存储在记录的数据页中。 在InnoDB中,如果一个varchar类型的列的长度小于等于768个字节,那么它会被存储在记录的数据页中。如果一个varchar类型的列的长度超过了768个字节,那么它会被存储在单独的页中,并且在记录中只存储一个指向这个页的指针。 此外,由于InnoDB使用了行级锁定,每个记录都需要存储一个事务ID,用于实现MVCC(多版本并发控制)。因此,在InnoDB中,每个记录头还需要存储一个6字节的事务ID和一个2字节的回滚指针。 综上所述,当使用varchar类型时,需要注意其实际数据的长度和存储引擎的存储结构,以便更好地设计表结构和查询语句。 ### 回答2: MySQL的varchar存储结构确实是相当深奥的。在InnoDB存储引擎中,varchar类型的数据存储在表的记录中,其存储结构会影响数据写入、存储空间占用和查询性能。 首先,varchar类型的数据在记录中是以变长字符串的形式进行存储的。这意味着,varchar字占用的存储空间与其实际存储的数据长度相关,而不是固定的。相比之下,固定长度的数据类型(如char)在存储时会占用固定的存储空间,无论实际数据的长度是多少。 其次,varchar类型的数据在记录中的存储格式是由一个表示长度的字节和真实字符串数据构成的。这个长度字用于指示存储的实际数据的长度,使得数据库可以根据需要动态地分配存储空间,从而节省了存储空间。 此外,在InnoDB存储引擎中,varchar字的数据存储在页内部的某个位置,而不是直接存储在页上。这是由于InnoDB采用了B+树的数据结构来组织数据,为了节省存储空间和提高数据访问效率,varchar字的数据会被存储在叶子节点中。这样一来,在查询时可以更快地遍历和定位数据,提高查询性能。 综上所述,MySQL的varchar存储结构的深度体现在其变长存储方式、长度字和数据存储位置等方面。了解和理解这些存储结构对于正确使用varchar类型的字、优化存储空间和提高查询性能都是非常重要的。 ### 回答3: MySQL的varchar存储结构在InnoDB引擎中确实是一个很深入的话题。InnoDB引擎是MySQL的默认引擎,它采用了B+树索引来存储数据。在InnoDB的记录存储结构中,varchar类型字经过了一系列处理。 首先,InnoDB将每个记录分为固定长度部分和变长长度部分。varchar字属于变长长度部分。对于varchar字MySQL会额外存储一个指针,指向数据存储区域。 其次,在实际存储varchar字值时,InnoDB会使用两种方式。对于较短的varchar字值,会直接将其存储在记录的数据域中。这样做的好处是可以减少额外的存储开销。 而对于较长的varchar字值,InnoDB会将其存储在一个称为“Overflow Page”的额外存储空间中。Overflow Page的指针存储在记录的数据域中。Overflow Page与主记录有一个单独的物理连接。 另外,需要注意的是,在InnoDB中,varchar字的长度是可变的,存储的最大长度由定义时的最大长度决定。这与char字是不同的,char字的长度是固定的。 总之,MySQL的varchar存储结构在InnoDB引擎中是相对复杂的。它采用了不同的存储方式来处理不同长度的字值,既保证了数据的存储效率,又满足了灵活性的要求。对于开发人员来说,了解varchar存储结构对于正确使用和优化数据库非常重要。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值