web-dev-qa-db-ja.com

mysqlで「指定されたキーが長すぎた最大キー長は255バイトです」を解決するにはどうすればよいですか?

Mysqlクライアント(emma)の1つからこのクエリを実行するときはいつでも:

CREATE TABLE `tbl_mappings` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `private_id` int(11) unsigned NOT NULL,
  `name` tinytext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`private_id`,`name`(255)),
  KEY `FK_tbl__private_integrations_mappings_tbl__private_integrations` (`private_id`),
  CONSTRAINT `FK_tbl__private_integrations_mappings_tbl__private_integrations` FOREIGN KEY (`private_id`) REFERENCES `tbl__private_integrations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

エラーが発生:指定されたキーが長すぎます最大キー長は255バイトです

私はmysqlサーバー5.7、ubuntu 16.04を使用しています

そして、[mysqld]の下のmy.cnfに設定を追加してみました。

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
default-storage-engine=InnoDB

その後、mysqlサービスを再起動しましたが、機能しません。

どんな助けでもありがたいです。ありがとうございました。

7
tushar patil

[〜#〜]編集[〜#〜]

問題はTINYTEXTデータ型に関連しているようです。 (私はInnoDBまたはMyISAMを使用して、MySQLバージョン5.7.17-0ubuntu0.16.04.1-logで観察された動作を複製できます。)

短い答え(回避策として、1071警告を解決する方法)は、データ型VARCHAR(255)TINYTEXTの代わりに使用することです。


さまざまな文字セット(utf8、utf8mb4、latin1)を使用し、InnoDBおよびMyISAMストレージエンジンを使用して、いくつかのテストケースを実行しました。 1071警告は、TINYTEXT列のインデックスで指定されたプレフィックス長に関連しているようです... MyISAMで動作を複製できるため、プレフィックス長のMySQL制限であるようです(特にInnoDBには関連していません)。 TINYTEXT以外のTEXTタイプではテストしていません。


前の回答

InnoDBテーブルのインデックスキーの長さの制限は767バイトです。

キー定義のname(255)は、nameの最初の255文字を指定しています。 MySQL utf8文字セットでは、文字は1〜3バイトを取ることができます。 3の255倍は765です。intprivate_idの4バイトを追加すると、769になり、最大値を超えます。

そのため、エラーが発生します。

それを解決するためのいくつかのアプローチ。

最も簡単なのは、インデックスに含まれる名前の文字数を減らすことです。

UNIQUE KEY `name` (`private_id`,`name`(254))

それがユースケースを満たさない場合は、廃止されたinnodb_large_prefix設定の使用を検討する必要があるかもしれません。 DYNAMICまたはCOMPRESSED行形式を使用する必要があります。ここでの議論を参照してください:

https://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format-specification.html

8
spencer7593

5つのソリューション here があります。

CHARACTER SET utf8mb4を使用しようとしたために制限に達した場合。次に、エラーを回避するために次のいずれかを実行します(それぞれに欠点があります)。

_⚈  Upgrade to 5.7.7 for 3072 byte limit -- your cloud may not provide this; 
⚈  Change 255 to 191 on the VARCHAR -- you lose any keys longer than 191 characters (unlikely?); 
⚈  ALTER .. CONVERT TO utf8 -- you lose Emoji and some of Chinese; 
⚈  Use a "prefix" index -- you lose some of the performance benefits. 
⚈  Stay with 5.6/5.5/10.1 but perform 4 steps to raise the limit to 3072 bytes: 

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)
_

一見すると、TINYTEXTを使用しないでください。接頭辞が必要ないVARCHAR(255)に変更してください。

一見すると、UNIQUE(x, y(255))veryが間違っている可能性があります。 「xの一部の組み合わせyは一意です」と書かれています。 xとは言わず、yallは一意です。

第四に... 5.7のどのバージョン? 5.7.15で正常に動作します。

_mysql> CREATE TABLE `tbl_mappings` (
    ->   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    ->   `private_id` int(11) unsigned NOT NULL,
    ->   `name` tinytext NOT NULL,
    ->   PRIMARY KEY (`id`),
    ->   UNIQUE KEY `name` (`private_id`,`name`(255)),
    ->   KEY `private_id` (`private_id`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    -> ;
Query OK, 0 rows affected (0.03 sec)

mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 5.7.15    |
+-----------+
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE tbl_mappings\G
*************************** 1. row ***************************
       Table: tbl_mappings
Create Table: CREATE TABLE `tbl_mappings` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `private_id` int(11) unsigned NOT NULL,
  `name` tinytext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`private_id`,`name`(255)),
  KEY `private_id` (`private_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)
_
1
Rick James