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

<div id="article_content" class="article_content csdn-tracking-statistics tracking-click" style="overflow: hidden;" data-dsm="post" data-mod="popu_519">
<div class="htmledit_views">
<h1 style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;"><span style="font-size: 14pt;">1.<span style="font-size: 18pt;">发现问题
<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;"> 今天在修改innodb表的某个列的长度时,报如下错误


<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;">


<div class="dp-Highlighter bg_html">
<div class="bar">
<div class="tools">[html] <a class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="#" target="_self">view plain<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> <a class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="#" target="_self">copy
<div style="position: absolute; left: 540px; top: 879px; width: 16px; height: 16px; z-index: 99;">

<span class="tracking-ad" data-mod="popu_169"> <a class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="#" target="_self">print<a class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;" href="#" target="_self">?

    altertabletest2modifycolumnidvarchar(500);
  1. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis767bytes

2.分析问题

2.1 问题原因分析

Highlighter bg_html">
[html]
    MysqLshowindexfromtest2\G;
  1. ***************************1.row***************************
  2. Table:test2
  3. Non_unique:1
  4. Key_name:id
  5. Seq_in_index:1
  6. Column_name:id
  7. Collation:A
  8. Cardinality:0
  9. Sub_part:NULL
  10. Packed:NULL
  11. Null:YES
  12. Index_type:BTREE
  13. Comment:
  14. Index_comment:
  15. 1rowinset(0.00sec)
 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索引长度限制

Highlighter bg_html">
[html]
    Fromthemanualathttp://dev.MysqL.com/doc/refman/5.6/en/create-table.html从5.6的官方文档中我们能找到如下双引号中解释
  1. "ForCHAR,VARCHAR,BINARY,andVARBINARYcolumns,indexescanbecreatedthatuSEOnlytheleadingpartofcolumnvalues,usingcol_name(length)Syntaxtospecifyanindexprefixlength.
  2. ...
  3. Prefixescanbeupto1000byteslong(767bytesforInnoDBtables).Notethatprefixlimitsaremeasuredinbytes,whereastheprefixlengthinCREATETABLEstatementsisinterpretedasnumberofcharacters..."对于myisam和innodb存储引擎,prefixes的长度限制分别为1000bytes和767bytes。注意prefix的单位是bytes,但是建表时我们指定的长度单位是字符。
  4. Autf8charactercanuseupto3bytes.Henceyoucannotindexcolumnsorprefixesofcolumnslongerthan333(MyISAM)or255(InnoDB)utf8characters.以utf8字符集为例,一个字符占3个bytes。因此在utf8字符集下,对myisam和innodb存储引擎创建索引的单列长度不能超过333个字符和255个字符
>从5.6的官方文档中我们能找到如下双引号中解释
"For CHAR,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个字符


<div class="dp-Highlighter bg_html">
<div class="bar">
<div class="tools">[html] <a class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="#" target="_self">copy
<div style="position: absolute; left: 540px; top: 1860px; width: 16px; height: 16px; z-index: 99;">


<span class="tracking-ad" data-mod="popu_169"> <a class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="#" target="_self">?

    createtabletest2(idvarchar(256),primarykey(id));
  1. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis767bytes
##对于innodb表,索引列长度大于255时,会报错。

<p style="font-family: Arial; font-size: 14px; line-height: 26px;"> 从上面可以看出,MysqL 在创建单列索引的时候对列的长度是有限制的 myisam和innodb存储引擎下长度限制分别为1000 bytes和767 bytes。(注意bytes和character的区别)


2) 组合索引长度限制
<p style="font-family: Arial; font-size: 14px; line-height: 26px;"> 对于innodb存储引擎,多列索引的长度限制如下:


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">每个列的长度不能大于767 bytes;所有组成索引列的长度和不能大于3072 bytes


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">参考如下例子(下面认使用的使用innodb存储引擎,smallint 占2个bytes,timestamp占4个bytes,utf8字符集。utf8字符集下,一个character占三个byte)


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">


<div class="dp-Highlighter bg_html">
<div class="bar">
<div class="tools">[html] <a class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="#" target="_self">copy
<div style="position: absolute; left: 540px; top: 2279px; width: 16px; height: 16px; z-index: 99;">
<span class="tracking-ad" data-mod="popu_169"> <a class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="#" target="_self">?

    MysqLcreatetabletest3(idvarchar(255),key(id));
  1. QueryOK,0rowsaffected(0.11sec)=
  2. MysqLdroptabletest3;
  3. QueryOK,0rowsaffected(0.03sec)
  4. MysqLcreatetabletest3(idvarchar(256),key(id));=),所以创建表失败
  5. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis767bytes
  6. MysqLcreatetabletest3(idvarchar(255),namevarchar(255),name1varchar(255),name2varchar(255),name3varchar(5),key(id,name,name1,name2,name3));=(255*4+=),所以表创建失败
  7. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis3072bytes
  8. MysqLcreatetabletest3(idvarchar(255),name3varchar(4),name3));
  9. QueryOK,0rowsaffected(0.09sec)
 create table test3(id varchar(255),key(id));
Query OK,0 rows affected (0.11 sec)  >>
MysqL> drop table test3;
Query OK,0 rows affected (0.03 sec)

MysqL> create table test3(id varchar(256),key(id)); >><span style="color: #ff0000;">索引列长度大于767(2563=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,name3)); <span style="color: #ff0000;"> >>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),name3 varchar(4),name3)); >>
Query OK,0 rows affected (0.09 sec)




<p style="font-family: Arial; font-size: 14px; line-height: 26px;"> 对于myisam存储引擎,多列索引长度限制如下:


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">每个列的长度不能大于1000 bytes,所有组成索引列的长度和不能大于1000 bytes


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">例子如下


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">


<div class="dp-Highlighter bg_html">
<div class="bar">
<div class="tools">[html] <a class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="#" target="_self">copy
<div style="position: absolute; left: 540px; top: 2790px; width: 16px; height: 16px; z-index: 99;">

<span class="tracking-ad" data-mod="popu_169"> <a class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="#" target="_self">?

    MysqLcreatetabletest3(idvarchar(334),key(id))=;索引列长度大于1000bytes(334*=),建表报错
  1. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis1000bytes
  2. MysqLcreatetabletest3(idvarchar(333),key(id))=;索引列长度小于1000bytes(333*=),建表成功
  3. QueryOK,0rowsaffected(0.07sec)
  4. MysqLcreatetabletest3(idvarchar(300),namevarchar(34),name))=;多列索引,所有列长度大于1000bytes建表报错
  5. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis1000bytes
  6. 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),name)) engine=myisam; >>多列索引,所有列长度大于1000 bytes 建表报错
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
MysqL>




3. 问题解决方案

Syntax to specify an index prefix length.

Highlighter bg_html">
    innodb_large_prefix启用innodb_large_prefix参数能够取消对于索引中每列长度的限制(但是无法取消对于索引总长度的限制)
  1. 启用innodb_large_prefix有如下前提条件:
  2. Enablethisoptiontoallowindexkeyprefixeslongerthan767bytes(upto3072bytes)forInnoDBtablesthatusetheDYNAMICandCOMpressedrowformats.(Creatingsuchtablesalsorequirestheoptionvalues=and=.)启用innodb_large_prefix必须同时指定==,并且建表的时候指定表的row_format为dynamic或者compressed(MysqL5.6中row_format认值为compact)
  3. SeeSection14.6.7,“LimitsonInnoDBTables”fortherelevantmaximumsassociatedwithindexkeyprefixesundervarIoUssettings.
  4. FortablesusingtheREDUNDANTandCOMPACTrowformats,thisoptiondoesnotaffecttheallowedkeyprefixlength.
>启用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.

例子如下:

<div class="dp-Highlighter bg_html">
<div class="bar">
<div class="tools">[html] <a class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="#" target="_self">copy
<div style="position: absolute; left: 540px; top: 3646px; width: 16px; height: 16px; z-index: 99;">

<span class="tracking-ad" data-mod="popu_169"> <a class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="#" target="_self">?

    1.查看innodb_large_prefix,innodb_file_format参数
  1. MysqLshowvariableslike'innodb_large_prefix';
  2. +---------------------+-------+
  3. |Variable_name|Value|
  4. +---------------------+-------+
  5. |innodb_large_prefix|OFF|
  6. +---------------------+-------+
  7. 1rowinset(0.01sec)
  8. MysqLshowvariableslike'innodb_file_format';
  9. +--------------------+----------+
  10. |Variable_name|Value|
  11. +--------------------+----------+
  12. |innodb_file_format|Antelope|
  13. +--------------------+----------+
  14. 1rowinset(0.00sec)
  15. 2.建索引测试(innodb_large_prefix,innodb_file_format都为认值的情况下)
  16. MysqLcreatetabletest3(idvarchar(256),key(id));
  17. ERROR1709(HY000):Indexcolumnsizetoolarge.Themaximumcolumnsizeis767bytes.
  18. MysqLcreatetabletest3(idvarchar(255),name3));
  19. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis3072bytes
  20. ##索引列大于767bytes时报错,组合索引列的总长度大于3072bytes时报错
  21. 3.修改innodb_large_prefix,innodb_file_format参数
  22. MysqLsetglobal=;
  23. QueryOK,0rowsaffected(0.00sec)
  24. MysqLsetglobal=;
  25. QueryOK,0rowsaffected(0.00sec)
  26. 4.对row_format为dynamic格式表创建索引测试
  27. MysqLcreatetabletest3(idvarchar(256),key(id))=;
  28. QueryOK,0rowsaffected(0.14sec)
  29. MysqLcreatetabletest3(idvarchar(255),name3))=;
  30. ERROR1071(42000):Specifiedkeywastoolong;maxkeylengthis3072bytes
  31. ##=并且=时,对于row_format为dynamic的表可以指定索引列长度大于767bytes。但是索引列总长度的不能大于3072bytes的限制仍然存在
 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)

  1. 建索引测试(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),name3));
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

索引列大于767 bytes时报错,组合索引列的总长度大于3072 bytes时报错

  1. 修改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)

  2. 对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),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的限制仍然存在





<p style="font-family: Arial; font-size: 14px; line-height: 26px;">


<p style="font-family: Arial; font-size: 14px; line-height: 26px;">


<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;">


<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;">


<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;">


<p style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px;">

            </div>



                </div>

相关文章

优化MySQL数据库发布系统存储的方法有:1.mysql库主从读写分...
使用mysql的方法:在“我的电脑”→右键→“管理”→“服务”...
在mysql中查看root用户权限的方法:1.命令行启动mysql服务;...
MySQL主从复制是用来备份一个与主数据库一样环境的从数据库,...
运行mysql的方法1.启动mysql服务,在“我的电脑”→右键→“...
开启mysql的方法1.可以通过快捷键win+r,输入cmd,打开窗口,...