1.发现问题

今天在修改innodb表的某个列的长度时,报如下错误:

  1. alter table test2 modify column id varchar(500);
  2. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
alter table test2 modify column id varchar(500);
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

2.分析问题

2.1 问题原因分析

其实从上面的报错中我们已经能看是因为索引达到长度限制,所以报错。查看id列是否有索引:

  1. mysql> show index from test2\G;
  2. *************************** 1. row ***************************
  3. Table: test2
  4. Non_unique: 1
  5. Key_name: id
  6. Seq_in_index: 1
  7. Column_name: id
  8. Collation: A
  9. Cardinality: 0
  10. Sub_part: NULL
  11. Packed: NULL
  12. Null: YES
  13. Index_type: BTREE
  14. Comment:
  15. Index_comment:
  16. 1 row in set (0.00 sec)
mysql> show index from test2\G;
*************************** 1. row ***************************
Table: test2
Non_unique: 1
Key_name: id
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)

##删除id列的索引后, alter table test2 modify操作可以正常执行

2.2 关于mysql索引长度限制

1)单列索引长度限制

  1. From the manual at http://dev.mysql.com/doc/refman/5.6/en/create-table.html >>从5.6的官方文档中我们能找到如下双引号中解释
  2. "For CHAR, VARCHAR, BINARY, and VARBINARY columns, indexes can be created that use only the leading part of column values, using col_name(length) syntax to specify an index prefix length.
  3. ...
  4. Prefixes can be up to 1000 bytes long (767 bytes for InnoDB tables). Note that prefix limits are measured in bytes, whereas the prefix length in CREATE TABLE statements is interpreted as number of characters ...">>>对于myisam和innodb存储引擎,prefixes的长度限制分别为1000 bytes和767 bytes。注意prefix的单位是bytes,但是建表时我们指定的长度单位是字符。
  5. A utf8 character can use up to 3 bytes. Hence you cannot index columns or prefixes of columns longer than 333 (MyISAM) or 255 (InnoDB) utf8 characters.  >>以utf8字符集为例,一个字符占3个bytes。因此在utf8字符集下,对myisam和innodb存储引擎创建索引的单列长度不能超过333个字符和255个字符
From the manual at http://dev.mysql.com/doc/refman/5.6/en/create-table.html >>从5.6的官方文档中我们能找到如下双引号中解释
"For CHAR, VARCHAR, BINARY, and VARBINARY columns, indexes can be created that use only the leading part of column values, using col_name(length) syntax to specify an index prefix length.
...
Prefixes can be up to 1000 bytes long (767 bytes for InnoDB tables). Note that prefix limits are measured in bytes, whereas the prefix length in CREATE TABLE statements is interpreted as number of characters ...">>>对于myisam和innodb存储引擎,prefixes的长度限制分别为1000 bytes和767 bytes。注意prefix的单位是bytes,但是建表时我们指定的长度单位是字符。 A utf8 character can use up to 3 bytes. Hence you cannot index columns or prefixes of columns longer than 333 (MyISAM) or 255 (InnoDB) utf8 characters. >>以utf8字符集为例,一个字符占3个bytes。因此在utf8字符集下,对myisam和innodb存储引擎创建索引的单列长度不能超过333个字符和255个字符
  1. create table test2(id varchar(256),primary key(id));
  2. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
create table test2(id varchar(256),primary key(id));
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

##对于innodb表,索引列长度大于255时,会报错。


从上面可以看出,mysql 在创建单列索引的时候对列的长度是有限制的 myisam和innodb存储引擎下长度限制分别为1000 bytes和767 bytes。(注意bytes和character的区别)

2) 组合索引长度限制

对于innodb存储引擎,多列索引的长度限制如下:

每个列的长度不能大于767 bytes;所有组成索引列的长度和不能大于3072 bytes

参考如下例子(下面默认使用的使用innodb存储引擎,smallint 占2个bytes,timestamp占4个bytes,utf8字符集。utf8字符集下,一个character占三个byte)

  1. mysql> create table test3(id varchar(255),key(id));
  2. Query OK, 0 rows affected (0.11 sec)  >>索引列长度小于767(255*3=765),表创建成功
  3. mysql> drop table test3;
  4. Query OK, 0 rows affected (0.03 sec)
  5. mysql> create table test3(id varchar(256),key(id));  >>索引列长度大于767(256*3=768),所以创建表失败
  6. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
  7. 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));  >>innodb下多列索引,所有列长度和大于3072/3=1024 (255*4+5=1025),所以表创建失败
  8. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
  9. mysql> create table test3 (id varchar(255),name varchar(255),name1 varchar(255),name2 varchar(255),name3 varchar(4),key (id,name,name1,name2,name3));  >>
  10. Query OK, 0 rows affected (0.09 sec)
mysql> create table test3(id varchar(255),key(id));
Query OK, 0 rows affected (0.11 sec) >>索引列长度小于767(255*3=765),表创建成功 mysql> drop table test3;
Query OK, 0 rows affected (0.03 sec) mysql> create table test3(id varchar(256),key(id)); >>索引列长度大于767(256*3=768),所以创建表失败
ERROR 1071 (42000): Specified key was too long; max key length 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)); >>innodb下多列索引,所有列长度和大于3072/3=1024 (255*4+5=1025),所以表创建失败
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
mysql> create table test3 (id varchar(255),name varchar(255),name1 varchar(255),name2 varchar(255),name3 varchar(4),key (id,name,name1,name2,name3)); >>
Query OK, 0 rows affected (0.09 sec)

对于myisam存储引擎,多列索引长度限制如下:

每个列的长度不能大于1000 bytes,所有组成索引列的长度和不能大于1000 bytes

例子如下

  1. mysql> create table test3(id varchar(334),key(id)) engine=myisam; >>索引列长度大于1000 bytes (334*3=1002),建表报错
  2. ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
  3. mysql> create table test3(id varchar(333),key(id)) engine=myisam;  >>索引列长度小于1000 bytes (333*3=999),建表成功
  4. Query OK, 0 rows affected (0.07 sec)
  5. mysql> create table test3(id varchar(300),name varchar(34),key(id,name)) engine=myisam; >>多列索引,所有列长度大于1000 bytes 建表报错
  6. ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
  7. mysql>
mysql> create table test3(id varchar(334),key(id)) engine=myisam; >>索引列长度大于1000 bytes (334*3=1002),建表报错
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
mysql> create table test3(id varchar(333),key(id)) engine=myisam; >>索引列长度小于1000 bytes (333*3=999),建表成功
Query OK, 0 rows affected (0.07 sec) mysql> create table test3(id varchar(300),name varchar(34),key(id,name)) engine=myisam; >>多列索引,所有列长度大于1000 bytes 建表报错
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
mysql>

3. 问题解决方案

1) using col_name(length) syntax to specify an index prefix length.

对列的前面某部分创建索引

2) 启用innodb_large_prefix参数

  1. innodb_large_prefix >>启用innodb_large_prefix参数能够取消对于索引中每列长度的限制(但是无法取消对于索引总长度的限制)
  2. 启用innodb_large_prefix有如下前提条件:
  3. Enable this option to allow index key prefixes longer than 767 bytes (up to 3072 bytes) for InnoDB tables that use the DYNAMIC and COMPRESSED row formats.(Creating such tables also requires the option values innodb_file_format=barracuda and innodb_file_per_table=true.) >>启用innodb_large_prefix必须同时指定innodb_file_format=barracuda,innodb_file_per_table=true,并且建表的时候指定表的row_format为dynamic或者compressed(mysql 5.6中row_format默认值为compact)
  4. See Section 14.6.7, “Limits on InnoDB Tables” for the relevant maximums associated with index key prefixes under various settings. >>
  5. For tables using the REDUNDANT and COMPACT row formats, this option does not affect the allowed key prefix length.
innodb_large_prefix >>启用innodb_large_prefix参数能够取消对于索引中每列长度的限制(但是无法取消对于索引总长度的限制)
启用innodb_large_prefix有如下前提条件:
Enable this option to allow index key prefixes longer than 767 bytes (up to 3072 bytes) for InnoDB tables that use the DYNAMIC and COMPRESSED row formats.(Creating such tables also requires the option values innodb_file_format=barracuda and innodb_file_per_table=true.) >>启用innodb_large_prefix必须同时指定innodb_file_format=barracuda,innodb_file_per_table=true,并且建表的时候指定表的row_format为dynamic或者compressed(mysql 5.6中row_format默认值为compact)
See Section 14.6.7, “Limits on InnoDB Tables” for the relevant maximums associated with index key prefixes under various settings. >>
For tables using the REDUNDANT and COMPACT row formats, this option does not affect the allowed key prefix length.

例子如下:

  1. 1. 查看innodb_large_prefix,innodb_file_format参数
  2. mysql> show variables like 'innodb_large_prefix';
  3. +---------------------+-------+
  4. | Variable_name       | Value |
  5. +---------------------+-------+
  6. | innodb_large_prefix | OFF   |
  7. +---------------------+-------+
  8. 1 row in set (0.01 sec)
  9. mysql> show variables like 'innodb_file_format';
  10. +--------------------+----------+
  11. | Variable_name      | Value    |
  12. +--------------------+----------+
  13. | innodb_file_format | Antelope |
  14. +--------------------+----------+
  15. 1 row in set (0.00 sec)
  16. 2. 建索引测试(innodb_large_prefix,innodb_file_format都为默认值的情况下)
  17. mysql> create table test3(id varchar(256),key (id));
  18. ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.
  19. 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));
  20. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
  21. ##索引列大于767 bytes时报错,组合索引列的总长度大于3072 bytes时报错
  22. 3. 修改innodb_large_prefix,innodb_file_format参数
  23. mysql> set global innodb_large_prefix=1;
  24. Query OK, 0 rows affected (0.00 sec)
  25. mysql> set global innodb_file_format=BARRACUDA;
  26. Query OK, 0 rows affected (0.00 sec)
  27. 4. 对row_format为dynamic格式表创建索引测试
  28. mysql> create table test3(id varchar(256),key (id)) row_format=dynamic;
  29. Query OK, 0 rows affected (0.14 sec)
  30. 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)) row_format=dynamic;
  31. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
  32. ##innodb_large_prefix=1并且innodb_file_format=BARRACUDA时,对于row_format为dynamic的表可以指定索引列长度大于767 bytes。但是索引列总长度的不能大于3072 bytes的限制仍然存在
1. 查看innodb_large_prefix,innodb_file_format参数
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) 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)) 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): Specified key was too long; max key length is 767 bytes的更多相关文章

  1. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

    今天在MySQL 5.6版本的数据库中修改InnoDB表字段长度时遇到了"ERROR 1071 (42000): Specified key was too long; max key le ...

  2. ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes

    这个错误是我在安装ambari平台时,准备为ambari指定mysql数据库时,执行建表语句时遇到的. ERROR 1071 (42000): Specified key was too long; ...

  3. 【laravel5.6】 Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes

    在进行数据迁移时候报错: 特殊字段太长报错, php artisan migrate 现在utf8mb4包括存储emojis支持.如果你运行MySQL v5.7.7或者更高版本,则不需要做任何事情. ...

  4. Using innodb_large_prefix to avoid ERROR #1071,Specified key was too long; max key length is 1000 bytes

    Using innodb_large_prefix to avoid ERROR 1071        单列索引限制上面有提到单列索引限制767,起因是256×3-1.这个3是字符最大占用空间(ut ...

  5. laravel migrate时报错:Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

    今天在学习laravel的路由模型绑定时,在按照文档执行php artisan migrate时报错. In Connection.php line 664: SQLSTATE[42000]: Syn ...

  6. laravel错误1071 Specified key was too long; max key length is 1000 bytes

    Laravel 5.5 环境,php artisan migrate 之后,出现错误如题. 检查了一下,代码是这样的: $table->increments('id'); $table-> ...

  7. laravel 错误 1071 Specified key was too long; max key length is 1000 bytes

    laravel 执行 php artisan migrate 安装数据库报 1071 Specified key was too long; max key length is 1000 bytes ...

  8. 导入sql文件报错:1071 Specified key was too long; max key length is 767 bytes

    ref: https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-7 ...

  9. django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')

    环境介绍 Django (2.1)  Python 3.5.5 mysqlclient (1.4.2.post1) Mysql 5.6.28 RHEL 7.3 在migrate时候报错 model代码 ...

随机推荐

  1. css before和after伪元素应用

    1.说明 ":before" 伪元素可以在元素的内容前面插入新内容. ":after" 伪元素可以在元素的内容之后插入新内容. 伪元素默认展示为inline, ...

  2. 几款Android开发人员必备小工具

    在这里我介绍一下我常常在Android Studio里面使用的小工具吧,这些工具都能够在plugin里面搜索到. (当然了哈.我也是从网上找的.用着挺方便的,在这里总结一下) Gsonformat: ...

  3. ios8.1.3Cydia重装

    1.下载deb包 2.把包放到/var/mobile/Media/下 3.终端输入:dpkg -i /var/mobile/Media/*.deb 然后输入:su -c uicache mobile ...

  4. OpenGL学习(hello)

    #include <gl/glut.h> void display(void) { glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲以及深度缓冲 glColo ...

  5. 细说HTML元素的隐藏和显示

    CSS文档对HTML的显示和隐藏有2个属性可供选择: 1.display 2.visiblity 这2个有什么区别呢? display: display版本:CSS1/CSS2 兼容性:IE4+ NS ...

  6. LoadRunner设置检查点的几种方法介绍

    前段时间在群里跟大家讨论一个关于性能测试的 问题,谈到如何评估测试结果,有一个朋友谈到规范问题,让我颇有感触,他说他们公司每次执行压力测试的时候,都要求脚本中必须有检查点存在,不然测试结果 将不被认可 ...

  7. Mysql的批量导入类 MySqlBulkLoader

    在mssqlserver 中 对应的SqlBuckCopy类,进行批量数据插入. 在mysql 中,官方提供了MySqlBulkLoader 平行的工具: 不过里面有坑,具体坑是插入空值列 NULL的 ...

  8. 路径,通过navigation可以查看 *.class文件

    ?.class文件内的代码所在的文件的路径默认 举例1:读取项目根目录下的数据. private static void readRoot() throws FileNotFoundException ...

  9. Android开发学习之Gallery和GridView浅析

    一.Gallery的简介 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息.Gallery还可以和ImageSwitcher组件结合使用来 ...

  10. 配置Windows server 2008文件同步[转]

    众所周知,Linux系统可以用rsync来实现文件或目录的同步,windows系统下也一样可以.我们现在就用cwRsync来实现windows server 2008系统下的文件同步. 一.系统环境 ...