8.4.7 Limits on Table Column Count and Row Size表列计数和行大小的限制

This section describes limits on the number of columns in tables and the size of individual rows.本节介绍表中列数和单行大小的限制。

Column Count Limits列计数限制

MySQL has hard limit of 4096 columns per table, but the effective maximum may be less for a given table. MySQL对每个表有4096列的硬限制,但是对于给定的表,有效的最大值可能更小。The exact column limit depends on several factors:准确的柱极限取决于几个因素:

Row Size Limits行大小限制

The maximum row size for a given table is determined by several factors:给定表的最大行大小由几个因素决定:

  • The internal representation of a MySQL table has a maximum row size limit of 65,535 bytes, even if the storage engine is capable of supporting larger rows. MySQL表的内部表示具有65535字节的最大行大小限制,即使存储引擎能够支持更大的行。BLOB and TEXT columns only contribute 9 to 12 bytes toward the row size limit because their contents are stored separately from the rest of the row.BLOBTEXT列只对行大小限制贡献9到12字节,因为它们的内容与行的其余部分分开存储。

  • The maximum row size for an InnoDB table, which applies to data stored locally within a database page, is slightly less than half a page for 4KB, 8KB, 16KB, and 32KB innodb_page_size settings. InnoDB表的最大行大小适用于数据库页面中本地存储的数据,对于4KB、8KB、16KB和32KB innodb_page_size设置,该表的最大行大小略小于半页。For example, the maximum row size is slightly less than 8KB for the default 16KB InnoDB page size. 例如,对于默认的16KB InnoDB页面大小,最大行大小略小于8KB。For 64KB pages, the maximum row size is slightly less than 16KB. 对于64KB的页面,最大行大小略小于16KB。See Section 15.22, “InnoDB Limits”.请参阅第15.22节,“InnoDB限制”

    If a row containing variable-length columns exceeds the InnoDB maximum row size, InnoDB selects variable-length columns for external off-page storage until the row fits within the InnoDB row size limit. 如果包含可变长度列的行超过InnoDB的最大行大小,InnoDB将选择可变长度列作为外部页外存储,直到该行符合InnoDB的行大小限制。The amount of data stored locally for variable-length columns that are stored off-page differs by row format. 对于页外存储的可变长度列,本地存储的数据量因行格式而异。For more information, see Section 15.10, “InnoDB Row Formats”.有关更多信息,请参阅第15.10节,“InnoDB行格式”

  • Different storage formats use different amounts of page header and trailer data, which affects the amount of storage available for rows.不同的存储格式使用不同数量的页眉和尾部数据,这会影响行的可用存储量。

Row Size Limit Examples行大小限制示例
  • The MySQL maximum row size limit of 65,535 bytes is demonstrated in the following InnoDB and MyISAM examples. 以下InnoDBMyISAM示例演示了MySQL的最大行大小限制65535字节。The limit is enforced regardless of storage engine, even though the storage engine may be capable of supporting larger rows.无论存储引擎如何,都会强制执行该限制,即使存储引擎可能能够支持更大的行。

    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

    In the following MyISAM example, changing a column to TEXT avoids the 65,535-byte row size limit and permits the operation to succeed because BLOB and TEXT columns only contribute 9 to 12 bytes toward the row size.在下面的MyISAM示例中,将列更改为TEXT可以避免65535字节的行大小限制,并允许操作成功,因为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)

    The operation succeeds for an InnoDB table because changing a column to TEXT avoids the MySQL 65,535-byte row size limit, and InnoDB off-page storage of variable-length columns avoids the InnoDB row size limit.InnoDB表的操作成功,因为将列更改为TEXT可以避免MySQL 65535字节的行大小限制,而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)
  • Storage for variable-length columns includes length bytes, which are counted toward the row size. 可变长度列的存储包括长度字节,这些字节按行大小计算。For example, a VARCHAR(255) CHARACTER SET utf8mb3 column takes two bytes to store the length of the value, so each value can take up to 767 bytes.例如,VARCHAR(255) CHARACTER SET utf8mb3列需要两个字节来存储值的长度,因此每个值最多可以占用767字节。

    The statement to create table t1 succeeds because the columns require 32,765 + 2 bytes and 32,766 + 2 bytes, which falls within the maximum row size of 65,535 bytes:创建表t1的语句成功,因为这些列需要32765+2字节和32766+2字节,这在最大行大小65535字节之内:

    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)

    The statement to create table t2 fails because, although the column length is within the maximum length of 65,535 bytes, two additional bytes are required to record the length, which causes the row size to exceed 65,535 bytes:创建表t2的语句失败,因为尽管列长度在65535字节的最大长度范围内,但需要另外两个字节来记录长度,这会导致行大小超过65535字节:

    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

    Reducing the column length to 65,533 or less permits the statement to succeed.将列长度减少到65533或更小将允许语句成功。

    mysql> CREATE TABLE t2
    (c1 VARCHAR(65533) NOT NULL)
    ENGINE = InnoDB CHARACTER SET latin1;
    Query OK, 0 rows affected (0.01 sec)
  • For MyISAM tables, NULL columns require additional space in the row to record whether their values are NULL. 对于MyISAM表,NULL列需要行中额外的空间来记录其值是否为NULL。Each NULL column takes one bit extra, rounded up to the nearest byte.每个NULL列需要额外的一位,四舍五入到最接近的字节。

    The statement to create table t3 fails because MyISAM requires space for NULL columns in addition to the space required for variable-length column length bytes, causing the row size to exceed 65,535 bytes:创建表t3的语句失败,因为除了可变长度列长度字节所需的空间外,MyISAM还需要NULL列空间,导致行大小超过65535字节:

    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

    For information about InnoDB NULL column storage, see Section 15.10, “InnoDB Row Formats”.有关InnoDB空列存储的信息,请参阅第15.10节,“InnoDB行格式”

  • InnoDB restricts row size (for data stored locally within the database page) to slightly less than half a database page for 4KB, 8KB, 16KB, and 32KB innodb_page_size settings, and to slightly less than 16KB for 64KB pages.对于4KB、8KB、16KB和32KB的innodb_page_size设置,InnoDB将行大小(对于本地存储在数据库页面中的数据)限制为略小于数据库页面的一半,对于64KB页面,限制为略小于16KB。

    The statement to create table t4 fails because the defined columns exceed the row size limit for a 16KB InnoDB page.创建表t4的语句失败,因为定义的列超过了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=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.