MySQL VARCHAR(255)UTF8对于密钥太长,但最大长度为1000字节

Dav*_*rek 42 mysql utf8mb4

我知道有很多关于此的问题,但我认为我的数学是正确的.

  • MySQL为每个UTF8字符保留3个字节.
  • MyISAM允许长度为1000字节的密钥.
  • 我的UTF8 VARCHAR(255)应该255 * 3 = 765字节

除非UNQUE每个条目需要额外的200多个字节,为什么这不起作用?

mysql> ALTER TABLE entry ADD UNIQUE INDEX (name(255));
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
Run Code Online (Sandbox Code Playgroud)

我能做些什么吗?

编辑:

事实证明,限制是250.对于唯一索引,字符似乎计为4个字节,但我不知道为什么.

编辑2:

感谢Vladislav Vaintroub,charset确实是utf8mb4.这解决了这个谜.我没有看到有关此更改的任何文档.

我猜它通过隐式截断字段来构建非唯一索引,这对于唯一索引是不可接受的,所以它拒绝.

如果您重新输入您的评论作为答案,我很乐意接受.

解决方案:指定utf8,而不是utf8mb4(MySQL Admin不允许这样做,因此请手动创建表)

jse*_*ars 41

如果您正在使用utf8mb4,并且varchar列上的唯一索引的长度超过191个字符,则需要打开innodb_large_prefix以允许索引中的更大列,因为utf8mb4需要比utf8或latin1更多的存储空间.将以下内容添加到my.cnf文件中.

[mysqld]
innodb_file_format=barracuda
innodb_file_per_table=1
innodb_large_prefix=1
init_connect='SET collation_connection = utf8mb4_unicode_ci'
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
Run Code Online (Sandbox Code Playgroud)

有关MySQL 5.7文档的原因和未来的更多信息:

如果启用了innodb_large_prefix(MySQL 5.7.7中的默认设置),则使用DYNAMIC或COMPRESSED行格式的InnoDB表的索引键前缀限制为3072字节.如果禁用innodb_large_prefix,则对于任何行格式的表,索引键前缀限制为767字节.

innodb_large_prefix在MySQL 5.7.7中已弃用,将在以后的版本中删除.在MySQL 5.5中引入了innodb_large_prefix,以禁用大型索引键前缀,以便与不支持大索引键前缀的早期版本的InnoDB兼容.

总而言之,限制仅用于兼容性,并将在未来版本中增加.

  • 值得一提的是,配置文件中的布尔条目在 MySQL 5.5 中必须设置为“1”而不是“ON”,否则它们不会被考虑在内。此外,由于无法在 5.5 和 5.6 中设置默认行格式(*innodb_default_row_format* 系统变量已在 5.7.9 中添加),因此必须使用 `ROW_FORMAT=DYNAMIC` 创建表。 (2认同)

小智 7

MySQL保留UTF8字段的最大数量,即4字节,这就是为什么你超过了1000字节的限制.我的建议是创建小于255的varchar或创建没有UTF8的varchar.

这两种解决方案可能都不适合您,或者您已经尝试过了.

我能想到的唯一其他解决方案是将列拆分为2个小列并在这两个字段上创建唯一索引,但我相信您会得到与上面相同的错误.

既然你可能需要UTF8,我会认真考虑将varchar(255)列减少到250(或249)以使其工作.

  • @Alexios默认`utf8`编码在MySQL中是3字节,而`utf8_mb4`是4字节变量('utf32`是4字节固定) (4认同)
  • 我讨厌挑剔,但UTF-8编码的字符最多可达6个字节.每个字符四个字节意味着内部UCS-4(可能是基于C`wchar_t`的)表示.(实际上,我撒了谎.我喜欢挑剔.抱歉!) (3认同)

Ome*_*esh 7

任何需要更大密钥长度的人都应该查看innodb_large_prefix

访问http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_large_prefix