8.4.7 table 列数和行大小的限制

本节描述了对 table 中的列数和单个行的大小的限制。

列数限制

MySQL 对每个 table 有 4096 列的硬限制,但是对于给定的 table,有效最大值可能会更少。确切的列限制取决于几个因素:

  • 一个 table 的最大行大小限制了列的数量(可能还有大小),因为所有列的总长度不能超过该大小。参见行大小限制

  • 单个列的存储要求限制了给定最大行大小内的列数。某些数据类型的存储要求取决于存储引擎,存储格式和字符集等因素。参见第 11.7 节“数据类型存储要求”

  • 存储引擎可能会施加其他限制 table 列计数的限制。例如,InnoDB每个 table 的限制为 1017 列。参见第 14.23 节“ InnoDB 限制”。有关其他存储引擎的信息,请参见第 15 章,备用存储引擎

  • 每个 table 都有一个.frm文件,其中包含 table 定义。该定义以可能影响 table 中允许的列数的方式影响此文件的内容。参见.frm 文件结构施加的限制

行大小限制

给定 table 的最大行大小由几个因素决定:

  • MySQLtable 的内部 table 示具有 65,535 字节的最大行大小限制,即使存储引擎能够支持更大的行也是如此。 BLOBTEXT列仅占行大小限制的 9 到 12 个字节,因为它们的内容与其余行分开存储。

  • InnoDBtable 的最大行大小适用于数据库页面中本地存储的数据,对于 4KB,8KB,16KB 和 32KB innodb_page_size设置,该行的最大行大小略小于一半。例如,对于默认的 16KB InnoDB页面大小,最大行大小略小于 8KB。对于 64KB 页面,最大行大小略小于 16KB。参见第 14.23 节“ InnoDB 限制”

如果包含variable-length columns的行超过InnoDB的最大行大小,则InnoDB选择可变长度的列用于外部页外存储,直到该行适合InnoDB行大小的限制。对于行外存储的变长列,本地存储的数据量因行格式而异。有关更多信息,请参见第 14.11 节“ InnoDB 行格式”

行大小限制示例
  • 以下InnoDBMyISAM示例演示了 MySQL 最大行大小限制为 65,535 字节。不管存储引擎如何,都会强制执行该限制,即使存储引擎可能能够支持更大的行。
mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g VARCHAR(6000)) ENGINE=InnoDB CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used
table type, not counting BLOBs, is 65535. This includes storage overhead,
check the manual. You have to change some columns to TEXT or BLOBs
mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g VARCHAR(6000)) ENGINE=MyISAM CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used
table type, not counting BLOBs, is 65535. This includes storage overhead,
check the manual. You have to change some columns to TEXT or BLOBs

在下面的MyISAM示例中,将列更改为TEXT可以避免 65,535 字节的行大小限制,并允许操作成功,因为BLOBTEXT列仅对行大小贡献 9 至 12 个字节。

mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g TEXT(6000)) ENGINE=MyISAM CHARACTER SET latin1;
Query OK, 0 rows affected (0.02 sec)

对于InnoDBtable,该操作成功,因为将列更改为TEXT可以避免 MySQL 65,535 字节的行大小限制,而InnoDB可变长度列的页外存储可以避免InnoDB行大小限制。

mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g TEXT(6000)) ENGINE=InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.02 sec)
  • 可变长度列的存储包括长度字节,该长度字节计入行大小。例如,VARCHAR(255)字符集 utf8mb3列占用两个字节来存储值的长度,因此每个值最多可以占用 767 个字节。

创建 tablet1的语句成功,因为这些列需要 32,765 2 字节和 32,766 2 字节,这在最大行大小 65,535 字节之内:

mysql> CREATE TABLE t1
       (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.02 sec)

创建 tablet2的语句失败,因为尽管列长度在最大长度 65,535 字节以内,但仍需要两个额外的字节来记录该长度,这会导致行大小超过 65,535 字节:

mysql> CREATE TABLE t2
       (c1 VARCHAR(65535) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used
table type, not counting BLOBs, is 65535. This includes storage overhead,
check the manual. You have to change some columns to TEXT or BLOBs

将列长度减少到 65,533 或更短,可以使语句成功。

mysql> CREATE TABLE t2
       (c1 VARCHAR(65533) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.01 sec)
  • 对于MyISAM个 table,NULL列在行中需要额外的空间以记录其值是否为NULL。每个NULL列都多加一位,四舍五入到最接近的字节。

创建 tablet3的语句失败,因为MyISAM除了可变长度的列长度字节所需的空间外,还需要NULL列的空间,从而导致行大小超过 65,535 字节:

mysql> CREATE TABLE t3
       (c1 VARCHAR(32765) NULL, c2 VARCHAR(32766) NULL)
       ENGINE = MyISAM CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used
table type, not counting BLOBs, is 65535. This includes storage overhead,
check the manual. You have to change some columns to TEXT or BLOBs

有关InnoDB NULL列存储的信息,请参见第 14.11 节“ InnoDB 行格式”

  • InnoDB将 4KB,8KB,16KB 和 32KB innodb_page_size设置的行大小(用于数据库页面中本地存储的数据)限制为略小于数据库页面的一半,而对于 64KB 页面,则限制为小于 16KB。

创建 tablet4的语句失败,因为定义的列超出了 16KB InnoDB页的行大小限制。

mysql> CREATE TABLE t4 (
       c1 CHAR(255),c2 CHAR(255),c3 CHAR(255),
       c4 CHAR(255),c5 CHAR(255),c6 CHAR(255),
       c7 CHAR(255),c8 CHAR(255),c9 CHAR(255),
       c10 CHAR(255),c11 CHAR(255),c12 CHAR(255),
       c13 CHAR(255),c14 CHAR(255),c15 CHAR(255),
       c16 CHAR(255),c17 CHAR(255),c18 CHAR(255),
       c19 CHAR(255),c20 CHAR(255),c21 CHAR(255),
       c22 CHAR(255),c23 CHAR(255),c24 CHAR(255),
       c25 CHAR(255),c26 CHAR(255),c27 CHAR(255),
       c28 CHAR(255),c29 CHAR(255),c30 CHAR(255),
       c31 CHAR(255),c32 CHAR(255),c33 CHAR(255)
       ) ENGINE=InnoDB ROW_FORMAT=COMPACT DEFAULT CHARSET latin1;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using
ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768
bytes is stored inline.