Mysql系列之--InnoDB存储引擎
1、InnoDB存储引擎
InnoDB是MySQL默认的存储引擎,也是使用最广泛的存储引擎。用户使用客户端执行SQL命令请求时,MySQL服务器经历了连接管理、查询缓存、语法解析、查询优化、调用存储引擎。MySQL存储引擎负责数据的处理,内存中处理过后的数据刷入磁盘,或者磁盘数据写人内存。
2、InnoDB数据页
InnoDB存储引擎主要负责高效的将数据存储到磁盘或者从磁盘调取数据。存储到磁盘中及时关机重启数据依旧存在,而真正在处理数据的时候,是在内存中完成的,所以在查询数据的时候需要把磁盘中的数据读取到内存中,在插入或者修改数据时,需要将内存的数据写人到磁盘中。如果每次查询或者修改一条数据,就进行一次读或者写的IO操作,那么效率无疑是特别低,为了解决这个问题,InnoDB采用的方式是将数据划分为若干个页,以页作为内存和磁盘交互的基本单位,一般也得大小为16KB,也就是说一次从磁盘中读取16KB大小的数据到内存中,或者将内存中16KB大小的数据刷入到磁盘中。
3、InnoDB行格式
数据库记录数据的时候,分为表,一张表中有行(row)或者叫做记录为最小单位存储数据,这些记录或者行在磁盘上的存储方式被叫做行格式或者记录格式。InnoDB存储引擎设计了4类行格式,分别为Compact(紧凑的、密集的)、Redundant(冗余的)、Dynamic(动态)、Compressed(压缩)格式行,Mysql默认的行格式为Compact。
3.1、指定行格式
可以在创建表或者修改表语句中指定行格式,例如
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
ALTER TABLE 表名 ROW_FORMAT=行格式名称
示例:
CREATE TABLE `mysql_demo`.`user` (
`user_id` varchar(64) NOT NULL COMMENT '工号',
`updated_user` varchar(64) NULL DEFAULT NULL COMMENT '更新人',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户表' ROW_FORMAT = DYNAMIC;
可以看出来,指定了行格式为Dynamic动态的,同时指定了字符类型utf8mb4格式。
3.2、Compact行格式
从图中可以看出compact行格式下,一条完整的记录被分为记录的额外信息和记录的真实数据。
3.2.1、记录的额外信息
记录的额外信息可以看作是记录的元数据,分为变长字段长度列表、NULL值列表、记录头信息
1)变长字段长度列表
在Mysql中支持一些变长的数据类型,例如varchar、text、blob,可以把这些数据类型的字段称为变长字段,变长字段在时间适用时,长度是不固定的,所以数据库需要记录这些字段真实数据的占用长度。
在Compact行格式中把所有的变长字段的真实数据占用长度存放在记录的开头部分,形成了变长字段长度列表,按照列的顺序逆序存放。
例如有三个字段c1、c2、c3为变长字段类型varchar,又因为变长字段长度列表是逆序存储,按照16进制存储就为01 03 04,把这个字节长度串放入变长字段长度列表效果如下:
2)NULL值列表
在表中某些列允许存储NULL,如果将这些NULL存储到真实数据中,会很占用空间,为了节省空间,将这些NULL值统一记录在NULL值列表。创建表时,被 NOT NULL定义的字段是不允许存储NULL的,如果表中没有允许存储NULL的列,则NULL值列表不存在,否则每个运行NULL值得字段有一个二进制位,如果为1则表示为NULL,如果为0表示不为NULL。二进制位同时按照字段顺序逆序存储。
Mysql规定Null值列表必须用整数字节表示,如果有<=8个字段,则使用一个字节8位表示
如果一个表中有9个字段运行NULL值,则需要2个字节表示,然后将二进制位使用16进制表示,填加到NULL值列表如下:
3)记录头信息
除了变长字段长度列表、NULL值列表外,还有一个记录头信息,用来描述记录,记录头信息固定长度为5个字节,40个二进制位,每个为代表不同的意思。
3.3.2、记录的真实数据
对于数据库表,除了我们自己定义的列,数据库会默认添加一列,也叫做隐藏列。
说明:Mysql在生成主键的时候,首先会选择用户定义的主键作为主键,如果用户没有定义主键,则选择一个定义了Unique的列作为主键,如果也没有定义任何一个Unique的列,则会使用数据库的row_id作为主键,所以row_id是可选的,其他两个隐藏列是必须存在的。
3.3、Redundant行格式
Redundent行格式相比较于Compact行格式,是一种比较旧的行格式,整体类似于Compact行格式,有一些细节上的差异,不做过多说明。
如果使用的是MySql 5.6或者更高版本,建议使用Compact行格式,更加节省存储空间,Redundent行格式比较旧,有更好的兼容旧版本,如果使用的是比较低的Mysql版本,或者特殊的功能,可以使用Redundent行格式。
Redundent在存储Null值得时候,会分配固定长度(1字节),对于可变长字段,分配固定长度,不是实际长度,所以比较消耗空间资源。
3.4、Dynamic和Compressed
现在使用的Mysql 5.7版本中默认的是Dynamic,Dynamic和Compressed两种行格式和Compact行格式基本相同,只是在处理行溢出数据时不同
在Compact和Redundent行格式中,如果某一列的数据量过大,那么该列只会存储前768字节的数据和一个指向其他页的地址
而Dynamic和Compressed在处理行溢出时,不会存储前768字节数据,会把所有数据存储到其他页,真实数据处只存储其他页的地址