本节介绍表中列数和单个行大小的限制。
MySQL 对每个表的列数有硬性限制,为 4096 列,但对于给定表而言,实际最大值可能更小。确切的列数限制取决于几个因素
表的最大行大小限制了列的数量(以及可能的大小),因为所有列的总长度不能超过此大小。请参见 行大小限制。
单个列的存储需求限制了在给定最大行大小内适合的列数。某些数据类型的存储需求取决于存储引擎、存储格式和字符集等因素。请参见 第 13.7 节,“数据类型存储需求”。
存储引擎可能会施加额外的限制,限制表的列数。例如,
InnoDB
每个表的限制为 1017 列。请参见 第 17.21 节,“InnoDB 限制”。有关其他存储引擎的信息,请参见 第 18 章,替代存储引擎。功能键部分(请参见 第 15.1.15 节,“CREATE INDEX 语句”)作为隐藏的虚拟生成的存储列实现,因此表索引中的每个功能键部分都计入表总列数限制。
给定表的最大行大小由几个因素决定
MySQL 表的内部表示具有 65,535 字节的最大行大小限制,即使存储引擎能够支持更大的行也是如此。
BLOB
和TEXT
列仅对行大小限制贡献 9 到 12 字节,因为它们的内容与行的其余部分分开存储。对于
InnoDB
表而言,最大行大小(适用于本地存储在数据库页面内的数据)略小于 4KB、8KB、16KB 和 32KBinnodb_page_size
设置的一半页面。例如,对于默认的 16KBInnoDB
页面大小,最大行大小略小于 8KB。对于 64KB 页面,最大行大小略小于 16KB。请参见 第 17.21 节,“InnoDB 限制”。如果包含 可变长度列 的行超过了
InnoDB
的最大行大小,InnoDB
会选择可变长度列用于外部离页存储,直到行适合InnoDB
行大小限制为止。对于存储在离页的可变长度列,本地存储的数据量因行格式而异。有关更多信息,请参见 第 17.10 节,“InnoDB 行格式”。不同的存储格式使用不同的页面头和尾数据量,这会影响可用于行的存储量。
有关
InnoDB
行格式的信息,请参见 第 17.10 节,“InnoDB 行格式”。有关
MyISAM
存储格式的信息,请参见 第 18.2.3 节,“MyISAM 表存储格式”。
行大小限制示例
以下
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
表,该操作成功,因为将一列更改为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) CHARACTER SET utf8mb3
列需要 2 个字节来存储值的长度,因此每个值最多可以占用 767 个字节。创建表
t1
的语句成功,因为这些列需要 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)
创建表
t2
的语句失败,因为虽然列长度在 65,535 字节的最大长度内,但需要 2 个额外的字节来记录长度,这会导致行大小超过 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
表,NULL
列在行中需要额外的空间来记录它们的值是否为NULL
。每个NULL
列需要 1 个额外的位,向上取整到最接近的字节。创建表
t3
的语句失败,因为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
列存储的信息,请参见 第 17.10 节“InnoDB 行格式”。InnoDB
将行大小(对于在数据库页面中本地存储的数据)限制为略小于 4KB、8KB、16KB 和 32KBinnodb_page_size
设置的一半数据库页面,并且对于 64KB 页面,限制为略小于 16KB。创建表
t4
的语句失败,因为定义的列超过了 16KBInnoDB
页面的行大小限制。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=DYNAMIC DEFAULT CHARSET latin1; ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.