索引长度过长 ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

摘要:
mysql˃showindexfromtest2G;***************************1.行***************************表:test2Non_-unique:1关键字名称:idSeq_in_索引:1列名称:idCollation:A排序规则:A排序规则:0子部分:NULL打包:NULL空值:YESIndex_类型:BTREEComment:索引注释:1rowinsetmysql˃showindexfromtest2G;**************************1.行***************************表:test2Non_ unique:1键_名称:idSeq_in_索引:1列_名称:ID排序规则:A排序规则:0子部分:NULL打包:NULL空值:YESIndex_类型:BTREEComment:index_注释:1下集##删除ID列的索引后,可以正常执行altertabletest2修改操作。2.2关于MySQL索引长度限制。1) 单列索引长度限制。[html]viewplaincopyprint?注意,前缀的单位是字节,但我们在创建表时指定的长度单位是字符。因此,在utf8字符集下,索引myisam和innodb存储引擎的单个列的长度不能超过333个字符和255个字符Fromthemanualathttp://dev.mysql.com/doc/refman/5.6/en/create-table.html˃˃从5.6的官方文件中,我们可以找到以下双引号来解释“对于char、VARCHAR、BINARY和VARBINARY列,创建索引时使用列值的前导部分,使用col_namesyntax来指定和索引前缀长度……前缀长度最多为1000字节。请注意,前缀长度以字节为单位,其中前缀长度thinCREATETABLE语句是字符角色数。。。“˃˃˃对于myisam和innodb存储引擎,前缀分别限制为1000字节和767字节。Autf8字符最多可使用3个字节。因此,您不能将列或列前缀的长度设置为333或255个utf8字符。˃˃以utf8字符集为例,一个字符占三个字节。
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 test2G;  
  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 test2G;
*************************** 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.   
  6. 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.   
  4. mysql> drop table test3;  
  5. Query OK, 0 rows affected (0.03 sec)  
  6.   
  7. mysql> create table test3(id varchar(256),key(id));  >>索引列长度大于767(256*3=768),所以创建表失败  
  8. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes  
  9. 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),所以表创建失败  
  10. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes  
  11. 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));  >>  
  12. 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.   
  6. mysql> create table test3(id varchar(300),name varchar(34),key(id,name)) engine=myisam>>多列索引,所有列长度大于1000 bytes 建表报错  
  7. ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes  
  8. 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=barracudainnodb_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.   
  10. mysql> show variables like 'innodb_file_format';  
  11. +--------------------+----------+  
  12. | Variable_name      | Value    |  
  13. +--------------------+----------+  
  14. | innodb_file_format | Antelope |  
  15. +--------------------+----------+  
  16. 1 row in set (0.00 sec)  
  17.   
  18. 2. 建索引测试(innodb_large_prefix,innodb_file_format都为默认值的情况下)  
  19. mysql> create table test3(id varchar(256),key (id));    
  20. ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.  
  21.   
  22. 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));  
  23. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes  
  24. ##索引列大于767 bytes时报错,组合索引列的总长度大于3072 bytes时报错  
  25.   
  26. 3. 修改innodb_large_prefix,innodb_file_format参数  
  27. mysql> set global innodb_large_prefix=1;  
  28. Query OK, 0 rows affected (0.00 sec)  
  29. mysql> set global innodb_file_format=BARRACUDA;  
  30. Query OK, 0 rows affected (0.00 sec)  
  31.   
  32. 4. 对row_format为dynamic格式表创建索引测试  
  33. mysql> create table test3(id varchar(256),key (id)) row_format=dynamic;  
  34. Query OK, 0 rows affected (0.14 sec)    
  35.   
  36. 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;   
  37. ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes  
  38. ##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》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Unity资源Assetbundle使用emmylua调试slua下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CDH搭建Hadoop分布式服务器集群(java新手小白)

1首先对于一个java还白的小白,先理解CDH与Hadoop的关系 一、Hadoop版本选择。 Hadoop大致可分为Apache Hadoop和第三方发行第三方发行版Hadoop,考虑到Hadoop集群部署的高效,集群的稳定性, 以及后期集中的配置管理,业界多使用Cloudera公司的发行版,简称为CDH。 下面是转载的Hadoop社区版本与第三方发行版...

mssql性能优化

总结下SQL SERVER数据库性能优化相关的注意事项,在网上搜索了一下,发现很多文章,有的都列出了上百条,但是仔细看发现,有很多似是而非或者过时(可能对SQL SERVER6.5以前的版本或者ORACLE是适用的)的信息,只好自己根据以前的经验和测试结果进行总结了。我始终认为,一个系统的性能的提高,不单单是试运行或者维护阶段的性能调优的任务,也不单单是开...

php : mysql数据库操作类演示

设计目标:  1,该类一实例化,就可以自动连接上mysql数据库;  2,该类可以单独去设定要使用的连接编码(set names XXX)  3,该类可以单独去设定要使用的数据库(use XXX);  4,可以主动关闭连接; <?php /* 设计一个类:mysql数据库操作类 设计目标: 1,该类一实例化,就可以自动连接上mysql数据库...

PLSQL_性能优化系列13_Oracle Index Rebuild索引重建

2014-10-04 Created By BaoXinjian 一、摘要 索引重建是一个争论不休被不断热烈讨论的议题。当然Oracle官方也有自己的观点,我们很多DBA也是遵循这一准则来重建索引,那就是Oracle建议对于索引深度超过4级以及已删除的索引条目至少占有现有索引条目总数的20% 这2种情形下需要重建索引。近来Oracle也提出了一些与之相反...

Mysql InnoDB彻底释放磁盘空间

Innodb数据库对于已经删除的数据只是标记为删除,并不真正释放所占用的磁盘空间,这就导致InnoDB数据库文件不断增长。 如果需要彻底释放磁盘空间,则需要先导出数据,然后删除数据文件,最后导入数据。具体步骤如下: 使用mysqldump命令将InnoDB数据库导出。 停止MySQL服务。 删除所有InnoDB数据库文件和日志(ibdata1,ib_lo...

MySQL中的数据类型的长度范围和显示宽度(转)

长度范围是随数据类型就已经是固定的值,而显示宽度与长度范围无关。 以下是每个整数类型的存储和范围(来自MySQL手册) 类型 字节 最小值 最大值 (带符号的/无符号的) (带符号的/无符号的) TINYINT 1 -128 127 0 255 SMALLINT 2 -32768 32767 0 65535 MEDI...