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 字节的最大行大小限制,即使存储引擎能够支持更大的行也是如此。 BLOB和TEXT列仅占行大小限制的 9 到 12 个字节,因为它们的内容与其余行分开存储。
-
InnoDB
table 的最大行大小适用于数据库页面中本地存储的数据,对于 4KB,8KB,16KB 和 32KB innodb_page_size设置,该行的最大行大小略小于一半。例如,对于默认的 16KBInnoDB
页面大小,最大行大小略小于 8KB。对于 64KB 页面,最大行大小略小于 16KB。参见第 14.23 节“ InnoDB 限制”。
如果包含variable-length columns的行超过InnoDB
的最大行大小,则InnoDB
选择可变长度的列用于外部页外存储,直到该行适合InnoDB
行大小的限制。对于行外存储的变长列,本地存储的数据量因行格式而异。有关更多信息,请参见第 14.11 节“ InnoDB 行格式”。
-
不同的存储格式使用不同数量的页面标题和尾部数据,这会影响行可用的存储量。
-
有关
InnoDB
行格式的信息,请参见第 14.11 节“ InnoDB 行格式”。- 有关
MyISAM
存储格式的信息,请参见第 15.2.3 节“ MyISAMtable 存储格式”。
- 有关
行大小限制示例
- 以下
InnoDB
和MyISAM
示例演示了 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 字节的行大小限制,并允许操作成功,因为BLOB和TEXT列仅对行大小贡献 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)
对于InnoDB
table,该操作成功,因为将列更改为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.