指定的键太长;最大键长度为767字节?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (10)
  • 关注 (1)
  • 查看 (554)

当我执行以下命令时:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

我收到了一条错误消息:

#1071 - Specified key was too long; max key length is 767 bytes

关于第1栏和第2栏的信息:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

我认为……varchar(20)只需要21个字节varchar(500)只需要501字节。所以总字节是522,小于767。那么为什么我会收到错误信息呢?

#1071 - Specified key was too long; max key length is 767 bytes
提问于
用户回答回答于

767字节是MySQLVersion 5.6和InnoDB表(和以前的版本)的限制长度。MyISAM表的长度为1000字节。在MySQLVersion 5.7及以上版本中,这个限制已经增加到3072字节。

如果你在一个大char或varchar字段上设置了一个索引,该字段是utf8mb4编码的,则必须将最大索引前缀长度767字节(或3072字节)除以4,结果为191字节。这是因为utf8mb4字符的最大长度是4个字节。对于UTF 8字符,它将是三个字节,导致最大索引前缀长度为254。

您可以选择只对VARCHAR字段设置下限。

另一个选项(根据对这一问题的回应)是获取列的子集

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

当需要进行调整,以获得应用程序的关键,可以对数据模型进行检查,以查看是否有改进。

用户回答回答于

当使用utf8mb4时,字符数为4字节,而在UTF 8下,字符可计算为3字节。InnoDB数据库的限制是索引只能包含767字节。因此,当使用UTF 8时,可以存储255个字符(767/3=255),但使用utf 8mb4,只能存储191个字符(767/4=191)。

用VARCHAR(255)字段时使用utf 8mb4,unique_key在此:

常规索引只是用来帮助MySQL更快地搜索数据。整个字段不需要索引。

那么,为什么MySQL会自动为常规索引截断索引,但是在尝试为惟一索引执行时抛出一个显式错误呢?好吧,对于MySQL来说,如果要计算插入或更新的值是否已经存在,它需要索引整个值,而不仅仅是它的一部分。

在一天结束时,如果您希望在一个字段上拥有一个惟一的索引,那么该字段的全部内容必须符合索引。对于utf8mb4,这意味着将VARCHAR字段长度减少到191个字符或更少。如果不需要utf8mb4用于这个表或字段,可以将它返回到utf8,并能够保持255个长度字段。

用户回答回答于
用户回答回答于

我认为varchar(20)只需要21个字节,而varchar(500)只需要501个字节。所以总字节是522,小于767。那么为什么我得到了错误信息呢?

UTF 8每个字符需要3个字节来存储字符串,因此在您的示例中,20+500个字符=20个*3+500*3=1560字节多过允许767字节。

UTF 8的极限为767/3=255个字符,对于每个字符使用4个字节的UTF 8mb4,为767/4=191个字符

如果您需要使用比限制更长的列,则有两种解决方案可以解决此问题:

  1. 使用“更低级”的编码(每个字符所需的字节更少)
  2. 从列中创建hash表,并仅对其使用唯一索引。
用户回答回答于
Specified key was too long; max key length is 767 bytes

当使用latin-1字符集。如果你用utf8,在定义键列时,每个字符将被认为是3个字节。如果你用utf8mb4,在定义键列时,每个字符将被视为4个字节。因此,您需要将键字段的字符限制乘以1、3或4(在我的示例中),确定最大允许的字节数。

用户回答回答于

在查询之前运行此查询:

SET @@global.innodb_large_prefix = 1;

这将使限制增加到3072 bytes...

用户回答回答于

您使用的是什么字符编码?有些字符集(如UTF-16等)每个字符使用一个以上字节。

用户回答回答于

MySQL假定字符串中每个字符的字节数最糟糕。对于MySQL 'utf8'编码,这是每个字符的3字节,因为编码不允许超出U+FFFF的字符。对于MySQL的utf8mb4编码,每个字符有4个字节,因为这是MySQL所称的实际UTF-8。

因此,假设您使用的是‘UTF 8’,那么您的第一列将占用60字节的索引,而第二列将占用另外1500字节。

用户回答回答于

当你达到限制值的时候。设置如下。

  • INNODButf8VARCHAR(255)
  • INNODButf8mb4VARCHAR(191)
用户回答回答于

如果有人对INNODB/utf-8有问题,请将UNIQUE索引VARCHAR(256)字段,切换到VARCHAR(255)似乎255才是限制。

所属标签

可能回答问题的人

  • HKC

    红客学院 · 创始人 (已认证)

    26 粉丝7 提问5 回答
  • Dingda

    Dingda · 站长 (已认证)

    4 粉丝0 提问3 回答
  • 西风

    renzha.net · 站长 (已认证)

    9 粉丝1 提问3 回答
  • 螃蟹居

    1 粉丝0 提问2 回答

扫码关注云+社区

领取腾讯云代金券