Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到槽,上面的过程都与页的内部结构相关,本文将详细的阐述。

3.4 行溢出

我们在介绍另外两种行格式DynamicCompressed之前,先介绍下行溢出

InnoDB存储引擎可以将一条记录中的数据存储在真正的数据页面之外。下面将举例说明这一点,先创建一个数据表。

65535字节是VarCahr类型存储的最大长度,而ASCII码一个字符占一个字节,因此我们指定的VARCHAR(65535)就表示其存储的字符数是65535,这些字符占65535字节,正好是VARCHAR数据类型存储字节的上限。

如果您还不理解就可以不指定字符集试试。

上面的语句将会报错。

这是因为不指定字符集时,默认使用的是utf-8,一个字符占3个字节,因此存储的字符上限就是65535/3=21845。

言归正传,我们再来执行下最开始的建表语句。

居然还是报错了,错误信息如下。

这是为什么呢?其实是因为VARCHAR的数据是变长的,需要2个字节额外的空间来记录数据的长度,1个字节标识NULL值信息,因此存储空间不能够达到65535字节,只能达到65532字节。

当然,我们可以加上非空约束,这样就不用记录NULL值列表了。

我们之前介绍过一个页的大小是16kb,也就是16384字节,而现在我们一个字段就比它大。这就会导致行溢出

CompactRuduntant两种行格式中,对于占用空间非常大的列,在存储真实数据时只会存储真实数据的一部分。将剩余的数据存储到其它页中进行分页存储

3.5 Dynamic和Compressed行格式

Dynamic和Compressed行格式与Compact大体是相同的,不过这两种行格式对于行溢出的处理策略与Compact不同。

它们采取了完全行溢出的策略。也就是数据页不存储任何溢出真实数据,只是存储指针,将真实数据完全存储到其它页中。

Compressed还采用了zlib算法对数据进行压缩,因此对于BLOB、TEXT、VARCHAR等大长度类型的数据能够进行有效的存储。


3.6 Redundant行格式

Redundant是Mysql5.0之前InnoDB的行格式。Mysql5.0支持Redundant是为了兼容以前版本的页格式,其格式如下。我们可以对比之前Compact行格式。

我们可以发现,Redundant采用字段长度偏移列表来定位数据,而Compact采用变长字段长度列表和Null值列表。如果是Compact行格式,不是变长数据就不会记录变长字段长度列表。而Redundant行格式必须所有列(包括隐藏列)的偏移长度都逆序进行记录,因此其名字是Redundant(冗余的)。


另外,其存储的是字段与记录开始位置的偏移长度,不如变长列表直接存储长度直观。

另外,Redundant因为所有的字段的偏移长度都记录了,也不用担心Null值导致记录的位置对不起的问题,所以没有Null值列表。

其记录头信息如下,黄色是较Compact多的属性信息。它也没有Record_type属性。了解即可。


4.区、段和碎片区

4.1 为什么要有区

页与页是通过双向链表进行连接的,如果以页为单位分配存储空间,逻辑上相邻的两个页在物理磁盘上实际距离比较远。在进行范围查询时,如果页与页之间的距离过远,在进行磁盘I/O操作时加载页就需要花许多时间(寻道、旋转等),就是随机I/O。磁盘和内存的速度相差了好几个数量级,磁盘随机I/O会花大量时间在数据页的查找加载上,是非常慢的。


出于性能考虑,我们希望能够在相邻的位置存取数据,以便能够顺序读取数据页。当然,我们也不能够让所有数据都存储到连续的空间,毕竟越大的连续空间在磁盘上越难找到。因此我们引入了区的概念。一个区就是64个在物理空间上连续的页。因此一个区的大小是16KB * 64 = 1MB。在表的数据量大的时候,我们就不再以页为单位进行存储空间的分配了,而是连续分配一个区,甚至是多个区。


4.2 为什么要有段

一个区中存放的页可能是数据页或者目录页,但当我们进行范围查询时,感兴趣的只有普通数据页。如果因为存放了目录页的原因,导致范围查找的效果大打折扣。我们希望一个区存储数据页就存储数据页,存储目录页就只存储目录页,因此出现了段的概念。常见的段有数据段、索引段、回滚段。段是逻辑上的概念。由若干零散的页(碎片区中的页,下一节介绍)和完整的区所组成。


4.3 为什么要有碎片区

InnoDB存储引擎一个聚簇索引会生成两个段,数据段和索引段,而每个段是以区作为单位申请存储空间的,如果表的数据量只有几条,也需要申请2M的空间么(一个区的大小为1M)?而且每增加一个索引,又需要增加2M,这空间浪费的也太严重了。


因此提出了碎片区,在一个碎片区中,可以让多个段共用一个公共空间,一些页给段A,一些页给段B,让空间得到充分的利用。就好比一个大广场可以给体育生大篮球,也可以给大妈跳广场舞,但它不是任何人所独有,而是一块公共空间。

现在我们可以知道InnoDB存储引擎分配存储空间的具体策略了。


在刚向表中插入数据时,先使用碎片区以页为单位进行存储空间的分配。

当某个段占用的存储空间达到了32个碎片区以后,我们再以完整的区为单位分配存储空间。

4.4 区的分类

区大体可以分成四个类型。


空闲区(Free):现在还没有用到这个区的任何页面。

有剩余空间的碎片区(Free-Frag):表示碎片区中还有可用的页面。

没有剩余空间的碎片区(Full-Frag)。

附属于某个段的区(FSEG):专属于给某一个段使用的完整的区。

前三种类型的区都是独立的,直属于表空间。FSEG是属于段的。


5.表空间

表空间是一个逻辑上的容器。可以划分为:独立表空间,系统表空间,撤销表空间,临时表空间等。


5.1 独立表空间

每个表对应一个表空间,也就是一个表的索引和数据会被单独保存在自己的表空间中,可以在不同的数据库之间进行数据的迁移。


其空间回收也比较方便,可以通过Drop Table操作自动回收表空间。对于统计分析或者日志表,还可以在删除大量数据之后,通过alter table tableName engine=innodb回收不用的空间。这个特性使碎片空间不会太影响性能。


独立表空间的结构由段、区、页等组成,不再赘述。


一个新建表的.idb文件大小是96kb,也就是6个页面大小(Mysql5.7),当然随着数据量的增加,有些idb也是自扩展的,表空间的文件大小会变大。在mysql5.6后,默认使用的都是独立表空间。可使用下面的语句查询。

5.2 系统表空间

与独立表空间的结构基本类似,整个MySQL进程只有一个表空间,会额外记录一些关于整个系统的数据,这是独立表空间中所没有的。比如在information_schema中提供了以INNODB_SYS开头的一些表,用于帮助我们查看与数据库系统相关的信息(相当于数据字典的副本)。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
3月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
3月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
102 4
|
5月前
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
23天前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
61 15
|
3月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
|
4月前
|
存储 关系型数据库 MySQL
MySQL覆盖索引解释
总之,覆盖索引就像是图书馆中那些使得搜索变得极为迅速和简单的工具,一旦正确使用,就会让你的数据库查询飞快而轻便。让数据检索就像是读者在图书目录中以最快速度找到所需信息一样简便。这样的效率和速度,让覆盖索引成为数据库优化师傅们手中的尚方宝剑,既能够提升性能,又能够保持系统的整洁高效。
125 9
|
5月前
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
113 12
|
6月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
105 0
|
1月前
|
安全 关系型数据库 MySQL
MySQL安全最佳实践:保护你的数据库
本文深入探讨了MySQL数据库的安全防护体系,涵盖认证安全、访问控制、网络安全、数据加密、审计监控、备份恢复、操作系统安全、应急响应等多个方面。通过具体配置示例,为企业提供了一套全面的安全实践方案,帮助强化数据库安全,防止数据泄露和未授权访问,保障企业数据资产安全。
|
16天前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
54 3

热门文章

最新文章

推荐镜像

更多