MySQL - 错误 1071 阻止更改字符集/排序规则,“指定的键太长......”
Posted
技术标签:
【中文标题】MySQL - 错误 1071 阻止更改字符集/排序规则,“指定的键太长......”【英文标题】:MySQL - change charset/collation prevented by error 1071, "specified key was too long..." 【发布时间】:2018-08-12 05:39:00 【问题描述】:我正在尝试将我的一个数据库表从 utf8_general_ci 切换到 utf8mb4。
ALTER TABLE d4b80le1jha CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
这会引发以下错误:
1071 - 指定的密钥太长;最大密钥长度为 1000 字节
我已阅读有关此错误消息的许多答案,但似乎无法解决我的问题。他们中的大多数都在谈论定义新索引,而不是如何处理现有索引。
我也尝试过以recommended here 运行以下命令,但没有任何区别:
SET @@global.innodb_large_prefix = 1;
一个加重因素可能是我使用 varchar 哈希作为主键。这是我无法控制的遗留功能。我没有在我的索引上设置明确的大小 - 我想知道这是否是我应该看的。
表:
Field Type Null Key Default
-------------------------------------------------------
id varchar(11) NO PRI NULL
link varchar(255) NO NULL
title varchar(255) NO NULL
description varchar(255) YES NULL
pubdate datetime NO NULL
img_url varchar(255) YES NULL
team_id varchar(11) NO MUL NULL
source_id varchar(11) NO NULL
hits int(11) YES NULL
hits int(11) YES NULL
索引:
Keyname Type Unique Packed Column Cardinality Collation Null
--------------------------------------------------------------------------------
PRIMARY BTREE Yes No id 13407 A No
Unique combo BTREE Yes No team_id A No
source_id A No
link 13407 A No
【问题讨论】:
我自己也遇到了这个错误信息。对我来说,将数据库引擎从MyISAM
切换到 InnoDB
允许更大的索引大小以适应 utf8mb4
字符集。减少列和索引的大小对我来说是行不通的,我不想在列级别使用字符集。由于 MyISAM 引擎将来会从 mysql 中移除,所以无论如何切换到 InnoDB 是必要的。
【参考方案1】:
这可能是您的Unique combo
索引造成了麻烦,我的意思是您在(team_id, source_id, link)
上的索引。该索引的 字符 总长度为 277,因此其总最大字节长度是 1108 的四倍。
你能做些什么呢?
将 link
列的字符长度减少到 228,因此索引的最大字符长度为 250。只要您的值仍然合适,这可能是最简单的。
重新创建提及link(228)
而不是仅提及link
的索引以仅索引link
的前导字符。我不知道这是否是个好主意;索引的目的是定义唯一约束。如果你不索引link
的整个值,你就没有这样做。
不要将表中的所有字符列转换为 utfmb4
字符编码,只需转换 title
和 description
列。这可能对你有用。为什么?您的 _id
哈希可能使用有限的字符集,根本不需要 unicode。您的 link
列值可能是 URL,也可以使用有限的 (latin1) 字符集。所以,title
和 description
可能需要用希伯来语或中文书写,或者包含表情符号或其他内容。这可能是您最好的解决方案。
(请注意,字符编码实际上是逐列指定的。为了方便起见,提供了转换整个表的能力。)
所以你可以这样做
ALTER TABLE d4b80le1jha
MODIFY title VARCHAR(255)
CHARACTER SET utf8mb4
COLLATE utf8mb4_bin;
ALTER TABLE d4b80le1jha
MODIFY description VARCHAR(255)
CHARACTER SET utf8mb4
COLLATE utf8mb4_bin;
最后,由于这两列是人类可读的文本,您可能希望使用utf8mb4_general_ci
而非utf8mb4_bin
来整理这些列。搜索和排序可能会更好地满足用户的期望。
【讨论】:
【参考方案2】:有 5 个步骤可以解决 5.5 和 5.6 中存在的问题,但在 5.7 中已默认消失。
如果您因为尝试使用 CHARACTER SET utf8mb4 而达到限制。这是一种方法:
将限制提高到 3072 字节:
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1;
logout & login (to get the global values);
ALTER TABLE tbl ROW_FORMAT=DYNAMIC; -- (or COMPRESSED)
http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes中给出了更多
【讨论】:
“执行以下操作之一”在这里很奇怪。您是否知道自己在说什么,或者只是 复制过去 对任何事情都足够好? ;) @changzhao - 哎呀。感谢您指出。是的,这是一个复制粘贴错误。以上是关于MySQL - 错误 1071 阻止更改字符集/排序规则,“指定的键太长......”的主要内容,如果未能解决你的问题,请参考以下文章
错误:#1071 - 指定的密钥太长;最大密钥长度为 1000 字节 - mysql 5.0.91
mysql 索引过长1071-max key length is 767 byte
mysql 索引过长1071-max key length is 767 byte
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes