1)InnoDB是将数据从内存存储到磁盘上的
2)InoDB将数据从内存中刷新到磁盘中是以页为基本单位,一般为16K
3)InoDB目前有四种行格式:compact(简洁的)、redundant(冗余的)、dynamic(动态的)、compress(压缩的)
指定、转换行格式语法:
create table 表名 (列的信息)ROW_FORMAT=行格式名称
alter table 表名 ROW_FORMAT=行格式名称
创建表并指定列字段类型:
插入2条记录:
compact行格式:
一条完整的信息分为记录的额外信息和记录的真实数据:
记录的额外信息:服务器为了描述真实数据不得不记录的信息,包括变长字段长度列表、null值列表、记录头信息
变长字段长度列表:MySQL支持varchar(M)、varbinary(M)、各种text、BLOB类型,用他们修饰的字段都是变长字段,而变长字段占用的空间分为真正的数据内容和占用的字节数
注意!!!在compact行格式中,变长字段长度列表中的数据是各个变长字段数据占用的字节数按倒序排列形成的列表,值为null的列的长度是不存储的。
示例如下:
变长字段长度列表中的数值:
1)假设某个字符集中表示一个字符最多需要使用的字节数为W,也就是使用SHOW CHARSET语句的结果中的Maxlen列,比方说utf8字符集中的W就是3,gbk字符集中的W就是2,ascii字符集中的W就是1
2)对于变长类型VARCHAR(M)来说,这种类型表示能存储最多M个字符(注意是字符不是字节),所以这个类型能表示的字符串最多占用的字节数就是M×W。
3)假设它实际存储的字符串占用的字节数是L。
所以确定使用1个字节还是2个字节表示真正字符串占用的字节数的规则就是:
1)如果M×W <= 255,那么使用1个字节来表示真正字符串占用的字节数。
也就是说InnoDB在读记录的变长字段长度列表时先查看表结构,如果某个变长字段允许存储的最大字节数不大于255时,可以认为只使用1个字节来表示真正字符串占用的字节数。
2)如果M×W > 255,则分为两种情况:
如果L <= 127,则用1个字节来表示真正字符串占用的字节数。
如果L > 127,则用2个字节来表示真正字符串占用的字节数。
重要总结!!!如果说存储的可变字段允许存储的最大字节数(MxW)超过255字节并且真实存储的字节数(L)超过127字节,那么变长字段长度列表中对应的占用2个字节来表示,否则用1个字节。
Null值列表:
1)统计表中允许存储null值的列有哪些
2)将每个允许存储null值的列按逆序的顺序在null值列表中以二进制的格式存储,如果字段列为null则记为0,不为null则记为1
3)null值列表中必须以整数个字节来表示,若不是整数则在高位补0
记录头信息:
用于描述记录的记录头信息,它是由固定的5个字节组成。也就是40个二进制位,不同的位代表不同的意思。
记录的真实信息:
除了我们自定义的数据信息外系统还会为每条记录添加默认的列,也成为隐藏列
实际上这几个列的真正名称其实是:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR,我们为了美观才写成了row_id、transaction_id和roll_pointer。
InoDB引擎对表的主键生成策略为:
优先使用用户自定义的主键作为主键,如果用户没有定义主键,则选取一个unique键作为主键,如果连 unique主键都没有的话,则InoDB会默认添加一个名为row_ID的隐藏列作为主键。
看这个图的时候我们需要注意几点:
1)表record_format_demo使用的是ascii字符集,所以0x61616161就表示字符串'aaaa',0x626262就表示字符串'bbb',以此类推。
2)注意第1条记录中c3列的值,它是CHAR(10)类型的,它实际存储的字符串是:'cc',而ascii字符集中的字节表示是'0x6363',虽然表示这个字符串只占用了2个字节,但整个c3列仍然占用了10个字节的空间,除真实数据以外的8个字节的统统都用空格字符填充,空格字符在ascii字符集的表示就是0x20。
3)注意第2条记录中c3和c4列的值都为NULL,它们被存储在了前边的NULL值列表处,在记录的真实数据处就不再冗余存储,从而节省存储空间。
我们说过在compact行格式下只会把定长类型的列的长度逆序存到变长字段长度列表中,而ASCII编码是定长编码字符集,而gbk中一个字符表示1-2个字节和utf-8中一个字符表示1-3个字节,都是不定长编码字符集。在示例表中C3列是char(10),那么C3的长度也会被存储到变长字段长度列表中。
对于char(M)类型的列来说,当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表中,而如果采用变长字符集时,该列占用字节数会被加到变长字段长度列表。
变长字符集的char(M)类型的列要求至少占用M个字节,而varchar(M)没有这样的要求。比方说对于使用utf-8字符集的char(10)来说,该列存储的数据的长度范围是10-30个字节。那么即使存储一个空字符串也会占用10个字节的空间,这么做的目的主要是方便以后更新该字段时,并且更新的字段长度小于10字节时可以直接更新而不需要重新分配一个新的记录空间避免之前的记录空间成为碎片。