web-dev-qa-db-ja.com

解決方法:指定されたキーが長すぎました。キーの最大長は767バイトです

私たちのサーバーは多くのテーブルを作成しており、そのうちの1つはLock_テーブルです。

PerconaでMySQL 5.5を使用しています。また、utf8_general_ciおよびutf8を使用しています。

Lock_テーブルに次のインデックスを作成すると、次のエラーがスローされます。

ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

次に、テーブル作成クエリを示します。

create table Lock_ (
    uuid_ VARCHAR(75) null,
    lockId LONG not null primary key,
    companyId LONG,
    userId LONG,
    userName VARCHAR(75) null,
    createDate DATE null,
    className VARCHAR(75) null,
    key_ VARCHAR(200) null,
    owner VARCHAR(255) null,
    inheritable BOOLEAN,
    expirationDate DATE null
);

インデックスクエリ:

create unique index IX_DD635956 on Lock_ (className, key_, owner);

この問題は、prodサーバーの1つで発生しています(以前はスタンドアロンのmysqlでしたが、後でperconaに移動しましたが、問題は両方のエディションに存在していました)。ただし、これは私たちの開発環境では問題なく機能しています。

それで、このエラーをスローしないように、prod環境のインデックス長などを更新する方法はありますか?

ありがとう

4
Prakash K

違いはUnicodeの長さの問題だと思います。文字ごとに1バイトの照合順序を使用していないため、キー内のフィールドの合計長は530character(75 + 200 + 255 )および530bytesではなく、530文字は、それらの文字列に格納している言語に応じて、767バイトを超える可能性があります(実際、 mysqlが、MS SQL ServerがNVARCHARカラム型で行うように、Unicodeデータを常に文字あたり2バイトとして格納する場合)。

Devで動作しているがライブではない理由:

  • Mysqlが固定長エンコーディングを使用しない場合、本番環境の一部の行の既存のデータが767バイトの制限を超えるのに十分な長さである可能性がありますが、Devにはそのような行はありません。 length()関数( http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_length )はバイト数を返しますが、文字なので、LENGTH(className)+LENGTH(key)+LENGTH(owner) > 767を選択して、そのような行をスキャンできます。
  • そうでない場合、照合設定が開発と本番で同一でない可能性があります。それらを確認してみてください。
3
David Spillett

(className, key_, owner)に必要なインデックスサイズの合計:

(75*3 + 1 + 1) + (200*3 + 2 + 1) + (255*3 + 2 + 1) = 1598 bytes 

InnoDB 各列のインデックスが最大767バイトの場合のみ、最大3500バイトのインデックスが許可されます 。 MyISAMは 合計1000文字 (ブロックサイズの変更)のみを許可します。 おそらく、本番データベースはInnoDBではなくMyISAMを使用しています。 多分あなたは本番でutf8mb4を使用していますか?それはあなたにそのエラーをもたらすでしょう。

また、 なぜvarchar(255)をお勧めしないのか もご覧ください。

2
jynus