▼▼▼mysql>Alter table tablename modify column 'clumnname' varchar(500) not null;ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
8.0版本:

5.7版本:
上面的意思是说如果启用了索引前缀参数(innodb_large_prefix ),那么InnoDB 存储引擎中的表的行格式为DYNAMIC or COMPRESSED时,prefixes的长度限制长度的最大限制为3072 bytes,关闭了索引前缀参数(innodb_large_prefix )时,prefixes的长度限制长度的最大限制为767 bytes。
总结如下:
对于myisam和innodb存储引擎,prefixes的长度限制分别为1000 bytes和767 bytes。注意prefix的单位是bytes,但是建表时我们指定的长度单位是字符。
以utf8字符集为例,一个字符占3个bytes。因此在utf8字符集下,对myisam和innodb存储引擎创建索引的单列长度不能超过333个字符和255个字符 。
测试过程如下:
关闭 innodb_large_prefix参数配置:

启用innodb_large_prefix参数配置:

从上面可以看出,mysql 在创建单列索引的时候对列的长度是有限制的 myisam和innodb存储引擎下长度限制分别为1000 bytes和767 bytes。(注意bytes和character的区别)
对于innodb存储引擎,多列索引的长度限制如下:
每个列的长度不能大于767 bytes;所有组成索引列的长度和不能大于3072 bytes
1)组合索引列长度限制

2)单列索引长度限制


每个列的长度不能大于1000 bytes,所有组成索引列的长度和不能大于1000 bytes
对列的前面某部分创建索引
▼▼▼之所以要限制索引键值的大小,是因为性能问题,而前缀索引能很好的解决这个问题。不需要修改任何系统变量。实例:mysql> show index from TEST;.................................. mysql> ALTER TABLE TEST DROP INDEX IDX_GEN_CODE;Query OK, 0 rows affected (0.00 sec)Records: 0 Duplicates: 0 Warnings: 0 mysql> CREATE IDX_GEN_CODE TEST ON TEST (CODE_NAME, CODE_VALUE1(12));Query OK, 0 rows affected (0.01 sec)Records: 0 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);Query OK, 1064 rows affected (0.08 sec)Records: 1064 Duplicates: 0 Warnings: 0
启用innodb_large_prefix参数能够取消对于索引中每列长度的限制(但是无法取消对于索引总长度的限制) 启用innodb_large_prefix有如下前提条件: 启用innodb_large_prefix必须同时指定innodb_file_format=barracuda,innodb_file_per_table=true,并且建表的时候指定表的row_format为dynamic或者compressed(mysql 5.6中row_format默认值为compact)

▼▼▼mysql> show variables like 'innodb_large_prefix';+---------------------+-------+| Variable_name | Value |+---------------------+-------+| innodb_large_prefix | OFF |+---------------------+-------+1 row in set (0.01 sec)mysql> show variables like 'innodb_file_format';+--------------------+----------+| Variable_name | Value |+--------------------+----------+| innodb_file_format | Antelope |+--------------------+----------+1 row in set (0.00 sec)
2. 建索引测试(innodb_large_prefix,innodb_file_format都为默认值的情况下)
▼▼▼mysql> create table test3(id varchar(256),key (id)); ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.mysql> create table test3(id varchar(255),name varchar(255),name1 varchar(255),name2 varchar(255),name3 varchar(5),key (id,name,name1,name2,name3));ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
##索引列大于767 bytes时报错,组合索引列的总长度大于3072 bytes时报错
3. 修改innodb_large_prefix,innodb_file_format参数
▼▼▼mysql> set global innodb_large_prefix=1;Query OK, 0 rows affected (0.00 sec)mysql> set global innodb_file_format=BARRACUDA;Query OK, 0 rows affected (0.00 sec)
4. 对row_format为dynamic格式表创建索引测试
▼▼▼mysql> create table test3(id varchar(256),key (id)) row_format=dynamic;Query OK, 0 rows affected (0.14 sec)
如果表已创建, 那么查看row_format的格式是否为dynamic;
▼▼▼mysql> show table status from MyDB where name='TEST'\G;

修改行类型:
▼▼▼mysql> ALTER TABLE TEST ROW_FORMAT=DYNAMIC;Query OK, 0 rows affected (0.05 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> create table test3(id varchar(255),name varchar(255),name1 varchar(255),name2 varchar(255),name3 varchar(5),key (id,name,name1,name2,name3)) row_format=dynamic; ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
##innodb_large_prefix=1并且innodb_file_format=BARRACUDA时,对于row_format为dynamic的表可以指定索引列长度大于767 bytes。但是索引列总长度的不能大于3072 bytes的限制仍然存在
ERROR 1071 (42000)解决方案:
启用系统变量innodb_large_prefix
注意:光有这个系统变量开启是不够的。必须满足下面几个条件:
系统变量innodb_large_prefix为ON
系统变量innodb_file_format为Barracuda
ROW_FORMAT为DYNAMIC或COMPRESSED
注意事项:
##innodb_large_prefix=1并且innodb_file_format=BARRACUDA时,对于row_format为dynamic的表可以指定索引列长度大于767 bytes。
但是索引列总长度的不能大于3072 bytes的限制仍然存在,要解决这个问题只能使用前缀索引或者减小字段长度。

更多精彩干货分享
点击下方名片关注
IT那活儿





