625

次のコマンドを実行したとき:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

次のエラー メッセージが表示されました。

#1071 - Specified key was too long; max key length is 767 bytes

column1 と column2 に関する情報:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

501バイトしか必要とvarchar(20)しないのに、21バイトしか必要ないと思います。varchar(500)したがって、合計バイト数は 522 で、767 未満です。では、なぜエラー メッセージが表示されたのでしょうか?

#1071 - Specified key was too long; max key length is 767 bytes
4

36 に答える 36

573

MySQL バージョン 5.6 (およびそれ以前のバージョン) の 767 バイトは、InnoDB テーブルのプレフィックス制限として規定されています。MyISAM テーブルの長さは 1,000 バイトです。この制限は、 MySQL バージョン 5.7 (およびそれ以降)では 3072 バイトに引き上げられました。

また、エンコードされた大きな char またはvarcharフィールドにインデックスを設定する場合utf8mb4は、767 バイト (または 3072 バイト) の最大インデックス プレフィックス長を 4 で割ると191になることにも注意する必要があります。これは、utf8mb4文字の最大長が 4 バイトであるためです。文字の場合utf8は 3 バイトになり、最大インデックス プレフィックス長は255 (またはヌル ターミネータを差し引いた 254 文字) になります。

VARCHARあなたが持っている1つのオプションは、フィールドに下限を設定することです.

別のオプション (この問題への回答によると) は、全体の量ではなく、列のサブセットを取得することです。つまり、次のようになります。

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

適用するキーを取得する必要があるため微調整しますが、このエンティティに関するデータ モデルを見直して、MySQL の制限に達することなく意図したビジネス ルールを実装できるようにする改善がないかどうかを確認する価値があるかどうか疑問に思います。 .

于 2009-11-29T03:52:38.547 に答える
426

INNODB / Utf-8UNIQUEでフィールドにインデックスを設定しようとして問題が発生している場合はVARCHAR(256)、 に切り替えてVARCHAR(255)ください。255が限界のようです。

于 2013-05-29T17:19:13.613 に答える
148

MySQL は、文字列内の文字あたりのバイト数について最悪のケースを想定しています。MySQL の 'utf8' エンコーディングでは、1 文字あたり 3 バイトU+FFFFです。MySQL 'utf8mb4' エンコーディングの場合、MySQL が実際の UTF-8 と呼ぶものであるため、1 文字あたり 4 バイトです。

したがって、「utf8」を使用していると仮定すると、最初の列は 60 バイトのインデックスを使用し、2 番目の列はさらに 1500 バイトを使用します。

于 2014-03-19T19:15:27.983 に答える
40

どの文字エンコーディングを使用していますか? 一部の文字セット (UTF-16 など) は、1 文字あたり複数のバイトを使用します。

于 2009-11-29T03:21:27.350 に答える
31

varchar(20) は 21 バイトしか必要としないのに対し、varchar(500) は 501 バイトしか必要としないと思います。したがって、合計バイト数は 522 で、767 未満です。では、なぜエラー メッセージが表示されたのでしょうか?

UTF8 では、文字列を格納するために 1 文字あたり 3 バイトが必要なので、この場合、20 + 500 文字 = 20*3+500*3 = 1560バイトとなり、これは許容される767バイトを超えます。

UTF8 の制限は 767/3 = 255 文字です。1 文字あたり 4 バイトを使用する UTF8mb4 の場合、767/4 = 191 文字です。


制限よりも長い列を使用する必要がある場合、この問題には 2 つの解決策があります。

  1. 「より安価な」エンコーディング (1 文字あたりのバイト数が少ないもの) を使用します。私
    の場合、記事の SEO 文字列を含む列に一意のインデックスを追加する必要がありました。そのため、列の長さは 767 バイトにすることができます。[A-z0-9\-]latin1_general_ci
  2. 列からハッシュを作成し、その上でのみ一意のインデックスを使用します
    。私にとっての他のオプションは、SEO のハッシュを格納する別の列を作成することでした。この列には、UNIQUESEO 値が一意であることを確認するためのキーがあります。KEYまた、検索を高速化するために、元の SEO 列にインデックスを追加します。
于 2016-12-23T09:03:00.207 に答える
28

エラーメッセージが表示される理由についての回答は、ここで多くのユーザーによって既に回答されています. 私の答えは、それを修正してそのまま使用する方法についてです。

このリンクから参照してください。

  1. MySQL クライアント (または MariaDB クライアント) を開きます。コマンドラインツールです。
  2. パスワードを聞かれるので、正しいパスワードを入力してください。
  3. このコマンドを使用してデータベースを選択しますuse my_database_name;

データベースが変更されました

  1. set global innodb_large_prefix=on;

クエリ OK、影響を受ける行は 0 (0.00 秒)

  1. set global innodb_file_format=Barracuda;

クエリ OK、影響を受ける行は 0 (0.02 秒)

  1. 簡単に管理できるように、phpMyAdmin などでデータベースに移動します。> データベースを選択 > テーブル構造を表示 > [操作] タブに移動します。> ROW_FORMATDYNAMICに変更し、変更を保存します。
  2. テーブルの構造タブに移動し、[一意] ボタンをクリックします。
  3. 終わり。これでエラーはなくなります。

この修正の問題は、db を別のサーバー (たとえば、localhost から実際のホスト) にエクスポートし、そのサーバーで MySQL コマンド ラインを使用できない場合です。そこで機能させることはできません。

于 2016-07-30T16:07:12.070 に答える
22
Specified key was too long; max key length is 767 bytes

latin-1文字セットを使用する場合にのみ 1 バイトが 1 文字に等しいため、このメッセージが表示されます。を使用utf8すると、キー列を定義するときに各文字が 3 バイトと見なされます。を使用utf8mb4すると、キー列を定義するときに各文字が 4 バイトと見なされます。したがって、キー フィールドが許可しようとしているバイト数を決定するには、キー フィールドの文字制限に 1、3、または 4 (私の例では) を掛ける必要があります。uft8mb4 を使用している場合は、ネイティブの InnoDB の主キー フィールドに 191 文字しか定義できません。767 バイトを超えないようにしてください。

于 2015-10-13T12:49:10.020 に答える
17

長い列のmd5の列を追加できます

于 2011-02-25T04:18:34.310 に答える
14

utf8mb4 を使用して VARCHAR(255) フィールドに UNIQUE インデックスを追加しようとしたときに、この問題が発生しました。問題はすでにここで十分に概説されていますが、これをどのように把握して解決したかについて、いくつかの実用的なアドバイスを追加したいと思います.

utf8mb4 を使用する場合、文字は 4 バイトとしてカウントされますが、utf8 では 3 バイトとしてカウントされます。InnoDB データベースには、インデックスに 767 バイトしか含めることができないという制限があります。そのため、utf8 を使用すると 255 文字 (767/3 = 255) を格納できますが、utf8mb4 を使用すると 191 文字 (767/4 = 191) しか格納できません。

VARCHAR(255)utf8mb4 を使用してフィールドに通常のインデックスを追加することは絶対にできますが、次のように、インデックスのサイズが 191 文字で自動的に切り捨てられunique_keyます。

インデックスが 191 文字で切り捨てられている Sequel Pro のスクリーンショット

通常のインデックスは、MySQL がデータをより迅速に検索できるようにするためにのみ使用されるため、これは問題ありません。フィールド全体にインデックスを付ける必要はありません。

では、なぜ MySQL は通常のインデックスに対して自動的にインデックスを切り捨てるのに、一意のインデックスに対して実行しようとすると明示的なエラーをスローするのでしょうか? 挿入または更新される値がすでに存在するかどうかを MySQL が判断できるようにするには、値の一部だけでなく、値全体を実際にインデックス化する必要があります。

結局のところ、フィールドに一意のインデックスを付けたい場合は、フィールドの内容全体がインデックスに収まる必要があります。utf8mb4 の場合、これは VARCHAR フィールドの長さを 191 文字以下に減らすことを意味します。そのテーブルまたはフィールドに utf8mb4 が必要ない場合は、utf8 に戻して、255 の長さのフィールドを保持できます。

于 2016-12-15T23:59:56.720 に答える
8

私はこのトピックについていくつかの検索を行い、最終的にいくつかのカスタム変更を取得しました

MySQL Workbench 6.3.7 バージョンの場合、グラフィカルな中間フェーズが利用可能です

  1. Workbench を起動し、接続を選択します。
  2. 管理またはインスタンスに移動し、オプション ファイルを選択します。
  3. Workbench が構成ファイルを読み取る許可を求めた場合は、[OK] を 2 回押して許可します。
  4. 中央に管理者オプション ファイル ウィンドウが表示されます。
  5. [InnoDB] タブに移動し、[全般] セクションでチェックされていない場合は innodb_large_prefix をチェックします。
  6. innodb_default_row_format オプション値を DYNAMIC に設定します。

6.3.7 より前のバージョンでは直接オプションを使用できないため、コマンド プロンプトを使用する必要があります。

  1. 管理者として CMD を起動します。
  2. ほとんどの場合、「C:\Program Files\MySQL\MySQL Server 5.7\bin」にあるため、コマンドは「cd \」「cd Program Files\MySQL\MySQL Server 5.7\bin」です。
  3. 次に、コマンド mysql -u userName -p databasescheema を実行します。それぞれのユーザーのパスワードを要求されました。パスワードを入力し、mysql プロンプトに入ります。
  4. いくつかのグローバル設定を設定する必要があります。以下のコマンドを 1 つずつ入力します。 set global innodb_large_prefix=on; グローバルな innodb_file_format=barracuda を設定します。グローバルな innodb_file_per_table=true を設定します。
  5. 最後に、必要なテーブルの ROW_FORMAT をデフォルトで COMPACT に変更する必要があります。これを DYNAMIC に設定する必要があります。
  6. 次のコマンドを使用します。 alter table table_name ROW_FORMAT=DYNAMIC;
  7. 終わり
于 2016-09-29T10:18:35.217 に答える
5

テーブルを作成するときに変更するだけutf8mb4で問題が解決しました。utf8例:CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

于 2018-07-21T15:31:14.630 に答える
5

これは私の問題を解決しました

ALTER DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;

于 2020-07-07T16:16:21.893 に答える
2

sql_modeのようなものかどうかを確認してください

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

そうであれば、に変更します

sql_mode=NO_ENGINE_SUBSTITUTION

また

my.cnf ファイルを変更してサーバーを再起動します (以下を入力)

innodb_large_prefix=on
于 2014-06-04T16:25:55.863 に答える
0

次のようなものを作成している場合:

CREATE TABLE IF NOT EXISTS your_table (
  id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(256) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY name (name)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

それは次のようなものでなければなりません

CREATE TABLE IF NOT EXISTS your_table (
      id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
      name varchar(256) COLLATE utf8mb4_bin NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

ただし、コードからその列の一意性を確認するか、varchar 列の MD5 または SHA1 として新しい列を追加する必要があります

于 2014-09-20T12:06:58.657 に答える
-1

私にとっては、「#1071 - 指定されたキーが長すぎました。最大キー長は 767 バイトです」という問題は、列のサイズを 200 に制限することで主キーと一意のキーの組み合わせを変更した後に解決されました。

ALTER TABLE `mytable` ADD UNIQUE (
`column1` (200) ,
`column2` (200)
);
于 2016-03-18T16:36:48.317 に答える
-4

問題のあるインデックス フィールドの CHARSET を「latin1」に変更します。
つまり、ALTER TABLE tbl CHANGE myfield myfield varchar(600) CHARACTER SET latin1 DEFAULT NULL;
latin1 は 1 文字に対して 4 バイトではなく 1 バイトを使用します

于 2013-12-27T13:14:25.627 に答える