48

我知道对此有很多问题,但我认为我的数学是正确的。

  • 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

对此我能做些什么吗?

编辑:

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

编辑2:

感谢 Vladislav Vaintroub,字符集确实是 utf8mb4。这就解开了谜团。我没有看到任何有关此更改的文档。

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

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

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

4

3 回答 3

46

如果您使用 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; SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

有关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 中已弃用,并将在未来的版本中删除。innodb_large_prefix 在 MySQL 5.5 中被引入以禁用大索引键前缀,以便与不支持大索引键前缀的早期版本的 InnoDB 兼容。

综上所述,限制只是为了兼容性,以后的版本会增加。

于 2016-04-04T14:48:30.127 回答
8

MySQL 为一个 4 字节的字段保留了最大数量,UTF8这就是为什么你要超过 1000 字节的限制。我的建议是创建varchar低于 255 或不创建UTF8.

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

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

由于您可能需要UTF8,我会认真考虑将varchar(255)列减少一点到 250(或 249)以使这项工作。

于 2011-05-31T04:39:52.700 回答
8

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

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

于 2012-07-18T11:38:14.533 回答