首页 > 数据库 > > 14.11 InnoDB 行存储和行格式
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html
14.11.1 InnoDB 行存储概述
行和关联列的存储会影响查询和DML操作的性能。 更多行在单个磁盘页面,查询和索引查找可以更快地工作,InnoDB缓冲池中需要的缓存内存更少,并且需要更少的I / O来写出数字和短字符串列的更新值
每个InnoDB表中的数据分为几页。 组成每个表的页面排列在称为B树索引的树数据结构中。 表数据和二级索引都使用这种类型的结构。 表示整个表的B树索引称为聚簇索引,它根据主键列进行组织。 索引数据结构的节点包含该行中的所有列(对于聚簇索引)或索引列和主键列(对于二级索引)的值
可变长度列是此规则的一个例外。 诸如BLOB和VARCHAR之类的列太长而无法放在B树页面上的列,存储在称为溢出页面的单独分配的磁盘页面上。 我们将此类列称为页外列。 这些列的值存储在单个链接的溢出页列表中,每个这样的列都有自己的一个或多个溢出页列表。 在某些情况下,长列值的全部或前缀存储在B树中,以避免浪费存储并消除读取单独页面的需要。
14.11.2 为一个表指定行格式
默认行格式由innodb_default_row_format定义,其默认值为DYNAMIC。 如果未明确定义ROW_FORMAT表选项或指定了ROW_FORMAT = DEFAULT,则使用默认行格式。
可以使用CREATE TABLE或ALTER TABLE语句中的ROW_FORMAT表选项显式定义表的行格式。 例如:
CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;
显式定义的ROW_FORMAT设置会覆盖隐式默认值。 指定ROW_FORMAT = DEFAULT等同于使用隐式默认值。
innodb_default_row_format选项可以动态设置:
mysql> SET GLOBAL innodb_default_row_format=DYNAMIC;
有效的innodb_default_row_format选项包括DYNAMIC,COMPACT和REDUNDANT。 不支持在系统表空间中使用的COMPRESSED行格式不能定义为默认行格式。 它只能在CREATE TABLE或ALTER TABLE语句中显式指定。 尝试将innodb_default_row_format设置为COMPRESSED会返回错误:
mysql> SET GLOBAL innodb_default_row_format=COMPRESSED; ERROR 1231 (42000): Variable 'innodb_default_row_format' can't be set to the value of 'COMPRESSED'
当未明确指定ROW_FORMAT选项或使用ROW_FORMAT = DEFAULT时,新创建的表使用innodb_default_row_format定义的行格式。 例如,以下CREATE TABLE语句使用innodb_default_row_format定义的行格式
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT) ROW_FORMAT=DEFAULT;
如果未显式指定ROW_FORMAT选项或使用ROW_FORMAT = DEFAULT,则任何重建表的操作也会以静默方式将表的行格式更改为innodb_default_row_format定义的格式。
表重建操作包括使用ALGORITHM = COPY的ALTER TABLE操作或使用ALGORITHM = INPLACE的ALTER TABLE操作,其中需要进行表重建。 OPTIMIZE TABLE也是一个表重建操作。
以下示例演示了一个表重建操作,该操作以静默方式更改未使用显式定义的行格式创建的表的行格式。
mysql> SELECT @@innodb_default_row_format;
+-----------------------------+ |
@@innodb_default_row_format |
+-----------------------------+
| dynamic |
+-----------------------------+
mysql> CREATE TABLE t1 (c1 INT);
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
TABLE_ID: 54
NAME: test/t1
FLAG: 33
N_COLS: 4
SPACE: 35
FILE_FORMAT: Barracuda
ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
mysql> SET GLOBAL innodb_default_row_format=COMPACT;
mysql> ALTER TABLE t1 ADD COLUMN (c2 INT);
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME LIKE 'test/t1' \G *************************** 1. row ***************************
TABLE_ID: 55
NAME: test/t1
FLAG: 1
N_COLS: 5
SPACE: 36
FILE_FORMAT: Antelope
ROW_FORMAT: Compact
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
在将现有表的行格式从REDUNDANT或COMPACT更改为DYNAMIC之前,请考虑以下潜在问题。
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR(5000), KEY i1(c2(3070)));
要查看表的行格式,请发出SHOW TABLE STATUS语句或查询INFORMATION_SCHEMA.TABLES。
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G
InnoDB表的行格式决定了它的物理行结构。
14.11.3 DYNAMIC 何 COMPRESSED 行格式
当使用ROW_FORMAT = DYNAMIC或ROW_FORMAT = COMPRESSED创建表时,InnoDB可以完全在页外存储长的可变长度列值(对于VARCHAR,VARBINARY,BLOB和TEXT类型),聚集索引记录仅包含20字节指向溢出页面的指针。 InnoDB还将长度大于或等于768字节的固定长度字段编码为可变长度字段。 例如,如果字符集的最大字节长度大于3,则CHAR(255)列可以超过768字节,就像使用utf8mb4一样。
是否在页外存储任何列取决于页面大小和行的总大小。 当行太长时,InnoDB会选择最长的列进行页外存储,直到聚簇索引记录适合B树页面。 小于或等于40字节的TEXT和BLOB列始终以串联方式存储。
DYNAMIC行格式保持在索引节点中存储整行的效率(如COMPACT和REDUNDANT格式),但DYNAMIC行格式避免了长列用大量数据字节填充B树节点的问题。 DYNAMIC格式基于如下思想:如果长数据值的一部分存储在页外,则通常最有效的是将所有值存储在页外。 使用DYNAMIC格式,较短的列可能保留在B树节点中,从而最小化任何给定行所需的溢出页数。
COMPRESSED行格式使用类似于页面外存储的DYNAMIC行格式,表和索引数据的其他存储和性能考虑因素被压缩并使用较小的页面大小。 使用COMPRESSED行格式,KEY_BLOCK_SIZE选项控制在聚簇索引中存储多少列数据,以及在溢出页面上放置多少。
DYNAMIC和COMPRESSED行格式都支持最多3072字节的索引键前缀。 此功能由innodb_large_prefix配置选项控制,该选项默认启用。 有关更多信息,请参阅innodb_large_prefix选项说明。
可以在file-per-table表空间或一般表空间中创建使用COMPRESSED行格式的表。 系统表空间不支持COMPRESSED行格式。 要将COMPRESSED表存储在每个表的文件表空间中,必须启用innodb_file_per_table,并且必须将innodb_file_format设置为Barracuda。 innodb_file_per_table和innodb_file_format配置选项不适用于常规表空间。 一般表空间支持所有行格式,但需要注意的是,由于物理页面大小不同,压缩和未压缩表不能在同一个通用表空间中共存。
DYNAMIC表可以存储在 file-per-table表空间,通用表空间和系统表空间中。 要在系统表空间中存储DYNAMIC表,必须将TABLESPACE [=] innodb_system表选项与CREATE TABLE或ALTER TABLE一起使用。 innodb_file_per_table和innodb_file_format配置选项不适用于一般表空间,在使用TABLESPACE [=] innodb_system表选项在系统表空间中存储DYNAMIC表时也不适用。
您可以通过禁用innodb_file_per_table并使用常规CREATE TABLE或ALTER TABLE语句将DYNAMIC表添加到系统表空间。 innodb_file_format设置被忽略。 DYNAMIC表始终使用Barracuda文件格式。
DYNAMIC和COMPRESSED行格式是COMPACT行格式的变体,因此以与COMPACT行格式相同的方式处理CHAR存储。
14.11.4 COMPACT 和 REDUNDANT 行格式
早期版本的InnoDB使用未命名的文件格式(现在称为Antelope)来存储数据库文件。 使用该文件格式,表使用ROW_FORMAT = COMPACT或ROW_FORMAT = REDUNDANT定义。 使用这些行格式,InnoDB在B树节点内的索引记录中存储最多768个字符的可变长度列(VARCHAR,VARBINARY,BLOB和TEXT类型),其余的存储在溢出页面上。 InnoDB还将长度大于或等于768字节的固定长度字段编码为可变长度字段,可以在页外存储。 例如,如果字符集的最大字节长度大于3,则CHAR(255)列可以超过768字节,就像使用utf8mb4一样。
使用Antelope文件格式,如果列的值为768字节或更少,则不需要溢出页面,并且可能导致I / O的一些节省,因为该值在B树节点中。 这适用于相对较短的BLOB,但可能导致B树节点填充数据而不是键值,从而降低其效率。 具有许多BLOB列的表可能导致B树节点变得太满,并且包含的行太少,使得整个索引的效率低于行较短或列值存储在页外的情况。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3142562/ ,如需转载,请注明出处,否则将追究法律责任。