主要介绍一下InnoDB引擎在表、索引、表空间等方面存在的一下限制,有助于在使用InnoDB引擎存储数据。 一下列举可能会在数据库管理中遇到的具体限制:
1.一张表最多可以创建1017个列,包含虚拟列在内。
2.一张表最多创建64个耳机索引。
3.对于表属性row_format值为 “DYNAMIC” 或 “COMPRESSED” 的表创建索引是索引键前缀长度限制为3072字节。表属性 row_format值为 “REDUNDANT” 或 “COMPAT” 的表创建索引是索引键前缀长度限制为767字节。
例如,表中字段属性varcahr长度为256字节,使用字符集utf8mb4,创建索引时表row_format=compat,因为256*3超过767字节,所以创建会失败,报错如下:
1071: Specified key was too long; max key length is 767 bytes
如果在创建MySQL实例时,通过innodb_page_size选项将InnoDB page size减小到8KB或4KB,那么索引键的最大长度会按比例减小,即在16KB page size下的3072字节的限制。也就是说,当页面大小为8KB时,最大索引键长度为1536字节,当页面大小为4KB时,最大索引键长度为768字节。
4.多列索引最多可以包含16个列,否则会报错:
ERROR 1070 (42000): Too many key parts specified; max 16 parts allowed
5.对于4KB、8KB、16KB和32KB的页面大小,最大行大小(不包括任何存储在页外的可变长列)略小于页面的一半。例如,默认的innodb_page_size为16KB,最大行大小约为8000字节。然而,对于一个64KB的InnoDB页面,最大行大小大约是16000字节。LONGBLOB和LONGTEXT列必须小于4GB,包括BLOB和TEXT列的总行大小必须小于4GB。
6.虽然InnoDB内部支持行大小大于65,535字节,但MySQL本身对所有列的总大小施加了行大小限制,即65,535。也就是说表中所有字段的长度不能超过65535字节,其实主要涉及到的还是varchar类的字符串类型,BLOB和TEXT类型官方说占9到12字符。
另外,根据存储引擎或字段的定义和字段的约束也会导致占用字节情况,需要在使用时注意。例如:
(1)创建表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)
(2)创建表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
(3)对于MyISAM表,NULL列需要行中额外的空间来记录它们的值是否为NULL。每个NULL列额外占用一个位,四舍五入到最近的字节。。所以创建表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引擎建表时,如果表字段过多,导致建表语句超过了数据库参数innodb_page_size的一半(例如默认16K,一半也就是8126字节)就会提示如下错误:
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.
所以建表时要特别注意大表的建表语句长度限制。解决方法也简单:
(1)注释sql_mode参数,设置innodb_strict_mode为0(set global innodb_strict_mode=0并刷新flush privileges)后就可以接触严格模式,就可以创建超限的表。但不建议这么做,对后期维护影响很大。
(2)新建库时直接将innodb page size调整成64K,但是对已有的数据库影响太大,需要初始化和很多操作。
(3)将表的ROW_FORMAT 设置为 COMPRESSED。
7.InnoDB日志文件的总最大容量为512GB。
8.表空间最小值大于10MB。表空间最大值取决于InnoDB页面大小。
InnoDB Page Size | MaxImum Tablespace Size |
---|---|
4KB | 16TB |
8KB | 32TB |
16KB | 64TB |
32KB | 128TB |
64KB | 256TB |
9.一个InnoDB数据库支持2的32次方个表空间。其中也包含一小部分undo和临时表存储的表空间。
10.共享表空间支持2的32次方个表。(2的32次方为4294967296)
11.不能创建与InnoDB内部列名称(包括DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR)匹配的表。此限制适用于使用任何字母大小写的名称。例如:
mysql> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
ERROR 1166 (42000): Incorrect column name 'db_row_id'
12.InnoDB存储引擎的库,使用SHOW TABLE STATUS命令时,不提供InnoDB表的精确统计信息,只提供了表保留的物理大小。行数只是SQL优化中使用的粗略估计。
13.ROW_FORMAT=COMPRESSED对于大于16KB的页面不支持。
14.一个MySQL实例使用了一个特定的InnoDB页面大小(innodb_page_size),不能使用来自一个不同页面大小的实例的数据文件或日志文件。