指定的键太长;mysql 5.6 中的最大密钥长度为 1000 字节

Hun*_*unt 5 mysql

其中一个应用程序服务器在我的内部创建数据库,mysql 但是当以下 create table 命令被执行时

 CREATE TABLE ofRoster (   

    rosterID              BIGINT          NOT NULL,   
    username              VARCHAR(64)     NOT NULL,   
    jid                   VARCHAR(1024)   NOT NULL,   
    sub                   TINYINT         NOT NULL,   

    ask                   TINYINT         NOT NULL,   
    recv                  TINYINT         NOT NULL,   
    nick                  VARCHAR(255),   
    PRIMARY KEY (rosterID),   
    INDEX ofRoster_unameid_idx (username),   
    INDEX ofRoster_jid_idx (jid) 

 )
Run Code Online (Sandbox Code Playgroud)

我收到以下错误

ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
Run Code Online (Sandbox Code Playgroud)

我已将我的默认引擎设置为,MyISAM因为我遇到以下错误InnoDB

specified key was too long max key length is 767 bytes
Run Code Online (Sandbox Code Playgroud)

我目前的引擎如下

+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MyISAM             | DEFAULT | MyISAM storage engine                                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| InnoDB             | YES     | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
Run Code Online (Sandbox Code Playgroud)

现在我真的不知道如何摆脱它,因为应用程序服务器本身正在 mysql 中自动创建数据库,所以我无法控制它。

我正在使用Server version: 5.6.10 MySQL Community Server (GPL)版本

列的字符集

+--------------------------+--------------------------------------------------------+
| Variable_name            | Value                                                  |
+--------------------------+--------------------------------------------------------+
| character_set_client     | utf8                                                   |
| character_set_connection | utf8                                                   |
| character_set_database   | latin1                                                 |
| character_set_filesystem | binary                                                 |
| character_set_results    | utf8                                                   |
| character_set_server     | latin1                                                 |
| character_set_system     | utf8                                                   |
| character_sets_dir       | /usr/local/mysql-5.6.10-osx10.6-x86_64/share/charsets/ |
+--------------------------+--------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

Mic*_*bot 4

您可以将 MySQL 5.6 中的最大 InnoDB 索引前缀大小增加到 3072 字节,方法是将其设置innodb_large_prefixON以及启用该索引所需的其他设置,如下所述:

\n\n

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

\n\n

这些更改应该允许这些索引对 InnoDB 表有效。

\n\n

对于字符集(我假设)utf8, aVARCHAR(1024)的索引需要 1024 x 3 = 3072 字节。

\n\n
\n\n

更新:

\n\n

我错误地显示了变量Yes应有的值ON

\n\n

但是也:

\n\n
\n

我认为它需要 3072+2 \xe2\x80\x93 ypercube

\n
\n\n

当我想到这一点时,听起来是正确的,因为当值是 255 字节或更小时,需要 1 个字节来存储值的大小,否则需要 2 个字节。

\n\n

然而,测试表明情况并非如此,在这种情况下 - InnoDB 使用BarracudaCOMPRESSED的行格式实际上可以索引 a 的完整大小......所以他们要么奇怪地记录它,要么行格式存储带外长度以及另一个元数据块,因此它不计入此格式的总字节数。VARCHAR(1024)COMPRESSED

\n\n

COMPRESSED不会将索引截断为前缀索引并抛出警告,直到您转到VARCHAR(1025).

\n\n
+-------+------+----------------------------------------------------------+\n| Level | Code | Message                                                  |\n+-------+------+----------------------------------------------------------+\n| Error | 1071 | Specified key was too long; max key length is 3072 bytes |\n+-------+------+----------------------------------------------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

它抛出警告而不是抛出错误的方式很好,但这对我们没有帮助,因为这仍然需要显式声明ROW_FORMAT来触发此行为。

\n\n

所以,我最初的答案仍然是错误的,因为你必须显式添加ROW_FORMAT=COMPRESSED到表定义的末尾。否则你仍然会遇到同样的旧错误。

\n\n

实际上,您在 5.6.10 中会遇到两个不同的错误。如果您尝试创建一个具有完全索引的表,VARCHAR(1024)您会得到以下结果:

\n\n
ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.\n
Run Code Online (Sandbox Code Playgroud)\n\n

...但是如果您尝试使用完全索引,VARCHAR(1025)您会得到以下结果:

\n\n
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是草率的代码,但底线是我的答案实际上并没有解决这个问题。

\n\n

我没有看到ROW_FORMAT=COMPRESSED默认使用的方法,如果可能的话,这似乎也不是一个好主意,我倾向于建议答案是......

\n\n

...这里没有现成的解决方法。latin1我的另一个想法是“字符集”,但和之间的差异utf8仍然不足以解释 1,024 与 1000 或 767。我很乐意支持一个更好的想法,但目前,我想不出一个此代码可以正常运行的 MySQL 服务器版本。

\n