InnoDB
REDUNDANT
COMPACT
DYNAMIC
COMPRESSED
表 15.15 InnoDB 行格式概述
VARBINARY
BLOB
TEXT
CHAR(255)
utf8mb4
CHAR(10)
VARCHAR
NULL
如果列的值是 768 字节或更少,则不会使用溢出页,并且可能会节省一些 I/O,因为该值完全存储在 B 树节点中。这适用于相对较短的 BLOB 列值,但可能会导致 B 树节点填充数据而不是键值,从而降低其效率。具有许多 BLOB 列的表可能会导致 B 树节点变得太满,并且包含的行太少,从而使整个索引的效率低于行较短或列值存储在页外的情况。
N
CEILING( N /8)
NOT NULL
VARCHAR 不会从列 中截断尾随空格 在内部,对于诸如 utf8mb3 and之类的可变长度字符集 utf8mb4 , InnoDB 尝试 通过修剪尾随空格来存储字节 列值的字节长度超过字节,则将尾随空格修剪为列值字节长度的最小值。列的最大长度 是最大字符字节长度× CHAR( N ) N CHAR( N ) N CHAR( N ) N
utf8mb3
CHAR( N )
N 为 保留 最少的字节。在许多情况下,保留最小空间可以使列更新就地完成,而不会导致索引页碎片化。相比之下, 列占用最大字符字节长度× 。 CHAR( N ) N CHAR( N ) N REDUNDANT
大于或等于 768 字节的固定长度列被编码为可变长度字段,可以跨页存储。例如, CHAR(255) 如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像 utf8mb4 . 类型) BLOB , TEXT 聚簇索引记录仅包含指向溢出页的 20 字节指针。大于或等于 768 字节的固定长度字段被编码为可变长度字段。例如, CHAR(255) 如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像 utf8mb4 . 列是否存储在页外取决于页大小和行的总大小。当一行太长时,选择最长的列进行页外存储,直到聚集索引记录适合 B 树 页。 小于等于40字节的列按行存储 TEXT 。 行格式保持了在索引节点合适的 DYNAMIC 情况下存储整行的效率( COMPACT 和 REDUNDANT 格式也是如此),但是 DYNAMIC 行格式避免了长列的大量数据字节填充B树节点的问题。行 DYNAMIC 格式基于这样的想法,即如果长数据值的一部分存储在页外,通常将整个值存储在页外是最有效的。使用 DYNAMIC 格式,较短的列可能会保留在 B 树节点中,从而最大限度地减少给定行所需的溢出页数。
DYNAMIC 行格式支持最多 3072 字节的索引键前缀 使用 DYNAMIC 行格式的表可以存储在系统表空间、file-per-table 表空间和通用表空间中。要将 DYNAMIC 表存储在系统表空间中,请禁用 innodb_file_per_table 并使用常规 CREATE TABLE or ALTER TABLE 语句,或者将 TABLESPACE [=] innodb_system 表选项与 CREATE TABLE or一起使用 ALTER TABLE 。该 innodb_file_per_table 变量不适用于一般表空间,也不适用于使用 TABLESPACE [=] innodb_system table选项 DYNAMIC 在系统表空间中存储表时。
innodb_file_per_table
CREATE TABLE
ALTER TABLE
TABLESPACE [=] innodb_system
DYNAMIC 行格式是行格式的变 体 COMPACT 。有关存储特性,请参阅 COMPACT 行格式存储特性 。 行格式提供与 COMPRESSED 行格式相同的存储特性和功能, DYNAMIC 但增加了对表和索引数据压缩的支持。
COMPRESSED 行格式使用与行格式类似的页外存储内部细节, 并 DYNAMIC 从表和索引数据中压缩额外的存储和性能考虑,并使用更小的页面大小。对于 COMPRESSED 行格式,该 KEY_BLOCK_SIZE 选项控制在聚集索引中存储多少列数据,以及将多少列数据放置在溢出页上。有关 COMPRESSED 行格式的更多信息,请参阅 第 15.9 节,“InnoDB 表和页面压缩” 。
KEY_BLOCK_SIZE
COMPRESSED 行格式支持最多 3072 字节的索引键前缀 。
COMPRESSED 可以在 file-per-table 表空间或通用表空间中创建 使用行格式的表。系统表空间不支持 COMPRESSED 行格式。要将 COMPRESSED 表存储在 file-per-table 表空间中, innodb_file_per_table 必须启用该变量。该 innodb_file_per_table 变量不适用于一般表空间。通用表空间支持所有行格式,但需要注意的是,由于物理页面大小不同,压缩表和未压缩表不能共存于同一通用表空间中。有关详细信息,请参阅 第 15.6.3.3 节,“通用表空间” 。
COMPRESSED 行格式是行格式的变 体 COMPACT 。有关存储特性,请参阅 COMPACT 行格式存储特性 。 innodb_default_row_format 变量定义,其默认值为 DYNAMIC . 当 ROW_FORMAT 表选项未明确定义或 ROW_FORMAT=DEFAULT 指定时,将使用默认行格式。
innodb_default_row_format
ROW_FORMAT
ROW_FORMAT=DEFAULT
可以使用or 语句 ROW_FORMAT 中的表选项 显式定义表的行格式 CREATE TABLE ALTER TABLE
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 or 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'
当未明确指定选项或使用选项 innodb_default_row_format 时,新创建的表使用变量 定义的行格式 。例如,以下语句使用 定义的行格式 。 ROW_FORMAT ROW_FORMAT=DEFAULT 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 变量定义的格式。 表重建操作包括 ALTER TABLE 使用 ALGORITHM=COPY 或 ALGORITHM=INPLACE 需要重建表的操作。有关详细信息,请参阅 第 15.12.1 节,“在线 DDL 操作” 。 OPTIMIZE TABLE 也是一个表重建操作。 以下示例演示了一个表重建操作,该操作以静默方式更改在未明确定义行格式的情况下创建的表的行格式。
ALGORITHM=COPY
ALGORITHM=INPLACE
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_TABLES WHERE NAME LIKE 'test/t1' \G *************************** 1. row *************************** TABLE_ID: 54 NAME: test/t1 FLAG: 33 N_COLS: 4 SPACE: 35 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_TABLES WHERE NAME LIKE 'test/t1' \G *************************** 1. row *************************** TABLE_ID: 55 NAME: test/t1 FLAG: 1 N_COLS: 5 SPACE: 36 ROW_FORMAT: Compact ZIP_PAGE_SIZE: 0 SPACE_TYPE: Single
在将现有表的行格式从 REDUNDANT 或 COMPACT 更改为 之前,请考虑以下潜在问题 DYNAMIC 。
REDUNDANT 和 行格式支持 的 COMPACT 最大索引键前缀长度为 767 字节,而 DYNAMIC 和 COMPRESSED 行格式支持的索引键前缀长度为 3072 字节。在复制环境中,如果 innodb_default_row_format 变量 DYNAMIC 在源上设置为 COMPACT ,在副本上设置为,则以下未明确定义行格式的 DDL 语句在源上成功但在副本上失败:
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR(5000), KEY i1(c2(3070)));
有关相关信息,请参阅 第 15.22 节,“InnoDB 限制” 。
innodb_default_row_format 如果源服务器上的设置与目标服务器上的设置不同,则 导入未明确定义行格式的表会导致模式不匹配错误 。有关详细信息,请参阅 第 15.6.1.3 节,“导入 InnoDB 表” 。 SHOW TABLE STATUS :
SHOW TABLE STATUS
mysql> SHOW TABLE STATUS IN test1\G *************************** 1. row *************************** Name: t1 Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 0 Avg_row_length: 0 Data_length: 16384 Max_data_length: 0 Index_length: 16384 Data_free: 0 Auto_increment: 1 Create_time: 2016-09-14 16:29:38 Update_time: NULL Check_time: NULL Collation: utf8mb4_0900_ai_ci Checksum: NULL Create_options: Comment:
或者,查询 INFORMATION_SCHEMA.INNODB_TABLES
INFORMATION_SCHEMA.INNODB_TABLES
mysql> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME='test1/t1'; +----------+------------+ | NAME | ROW_FORMAT | +----------+------------+ | test1/t1 | Dynamic | +----------+------------+