不同的存储引擎一般是为实现不同的特性来开发的,真实数据在不同存储引擎中的存放格式一般是不同的,甚至有的存储引擎(比如 MEMORY)都不用磁盘来存储数据,也就是对于使用 MEMORY 存储引擎的表来说,关闭服务器后表中的数据就消失了。 lnnoDB是MySQL 默认的存储引擎,也是我们最常用到的存储引擎。
当我们想从表中获取某些记录时, lnnoDB 存储引擎需要一条一条地把记录从磁盘上读出来么?不,这样重复访问磁盘会非常非常非常慢,lnnoDB 采取的方式是,将数据划分为若干个页 ,以页作为磁盘和内存之间交互的基本单位。lnnoDB 页的大小一般为16KB = 16384B 。也就是在一般情况下,一次最少从磁盘中读取 16KB 的内容到内存中,一次最少把内存中的 16KB 内容刷新到磁盘中。
Tips:系统变量innodb_page _size只能在第一次初始化MySQL数据目录时指定,运行过程中不可更改页面大小。
我们平时都是以记录为单位向表中插入数据的,这些记录在磁盘上的存放形式也被称为行格式或者记录格式,可以在创建或修改表的语句中指定记录所使用的行格式。目前有4种行格式:
COMPACT
:占用空间较小,适合具有大量重复数据的表。REDUNDANT
:不再被推荐使用,用于兼容旧版本。DYNAMIC
:支持更多的数据类型和功能,适用于各种情况。COMPRESSED
:将数据进行压缩,可以显著减小存储空间,但可能会增加CPU负担。1、变长字段长度列表(如果无变长字段,没有该部分)
变长字段列表仅存储非NULL列。
VARCHAR(M)、 BINARY(M)、各种 TEXT 类型、各种 BLOB 类型等变长字段占用的存储空间分为两部分:真正的数据内容 + 该数据占用的字节数。COMPACT 行格式中,所有变长字段的真实数据占用字节数都存放在记录的开头位置,各变长字段的真实数据占用的字节数按照列顺序逆序存放。
1个字节能表示的最大值为0xFF = 255,2个字节能表示的最大值为0xFFFF = 65535。给定以下符号表示。
W W W:某个字符集中最多需要W字节来表示一个字符,比如utf8mb4字符集中的W就是4
M M M:对于变长类型 VARCHAR(M),能存储最多M个字符
L L L:该变长字段实际存储的字符串占用的字节数是 L
如果该变长字段允许存储的最大字节数 M × W M\times W M×W 超过 255 字节,并且真实数据占用的字节数 L L L超过 127 字节,则使用2字节来表示真实数据占用的字节数,否则使用1字节。
如果某个字段占用的字节数特别多, InnoDB 有可能把该字段的值的一部分数据存放到所谓的溢出页中。
对于 CHAR(M)类型的列来说,当列采用的是定长编码的字符集时,该列占的字节数不会被加到变长字段长度列表:而如果采用变长编码的字符集时 该列占用的字节数就会被加到变长字段长度列表。
2、NULL值列表(如果无NULL值,没有该部分)
COMPACT 行格式把一条记录中值为 NULL 的列统一管理起来 ,存储到 NULL 值列表。对表中未限制Not Null
的列,按列顺序逆序存储二进制位,1代表NULL,0代表不为NULL。MYSQL规定NULL值列表必须为整数字节,若不足,在高位补0。
3、记录头信息(固定5字节)
如果某个字段占用的字节数特别多, InnoDB 有可能把该字段的值的一部分数据存放到所谓的溢出页中,在记录的真实数据处只会存储该列的部分数据,而把剩余的数据分散存储在几个其他的页中 然后在记录的真实数据处用 20 字节存储指向这些页的地址。
Compressed 和 Dynamic 这两个行格式和 Compact 非常类似,主要的区别在于处理行溢出数据时有些区别。
这两种格式采用完全的行溢出方式,记录的真实数据处不会存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页。而实际的数据都存储在溢出页中。
MySQL规定:一行记录除了 TEXT、BLOBs 类型的列(不包括隐藏列和记录头信息),限制最大为 65535 字节。
SO:要保证所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数 <= 65535