web-dev-qa-db-ja.com

#1071-指定されたキーが長すぎました。キーの最大長は1000バイトです

このタイトルの質問には以前に回答したことがありますが、読んでください。投稿する前に、このエラーに関する他の質問/回答をすべて読みました。

次のクエリで上記のエラーが発生しています。

CREATE TABLE IF NOT EXISTS `pds_core_menu_items` (
  `menu_id` varchar(32) NOT NULL,
  `parent_menu_id` int(32) unsigned DEFAULT NULL,
  `menu_name` varchar(255) DEFAULT NULL,
  `menu_link` varchar(255) DEFAULT NULL,
  `plugin` varchar(255) DEFAULT NULL,
  `menu_type` int(1) DEFAULT NULL,
  `extend` varchar(255) DEFAULT NULL,
  `new_window` int(1) DEFAULT NULL,
  `rank` int(100) DEFAULT NULL,
  `hide` int(1) DEFAULT NULL,
  `template_id` int(32) unsigned DEFAULT NULL,
  `alias` varchar(255) DEFAULT NULL,
  `layout` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`menu_id`),
  KEY `index` (`parent_menu_id`,`menu_link`,`plugin`,`alias`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

誰がそれを修正する理由と方法を知っていますか?キャッチは-この同じクエリは私のローカルマシンで完全に機能し、以前のホストでも同様に機能しました。 Btw.itは成熟したプロジェクト-phpdevshell-からのものなので、これらの人は自分が何をしているのか知っていると思いますが、あなたは決して知りません。

手がかりはありがたい。

PhpMyAdminを使用しています。

81
CodeVirtuoso

@Devartが言うように、インデックスの全長は長すぎます。

短い答えは、とにかくそのような長いVARCHARカラムにインデックスを付けるべきではないということです。インデックスは非常にかさばり、非効率的だからです。

ベストプラクティスは、プレフィックスインデックスを使用することです。したがって、データの左のサブストリングのみにインデックスを作成します。とにかく、ほとんどのデータは255文字よりずっと短くなります。

インデックスを定義するときに、列ごとにプレフィックス長を宣言できます。例えば:

...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...

しかし、特定の列に最適なプレフィックス長は何ですか?見つける方法は次のとおりです。

SELECT
 ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(`menu_link`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(`menu_link`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(`menu_link`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(`menu_link`),2) AS pct_length_100
FROM `pds_core_menu_items`;

menu_link列に指定された文字列長以下の行の割合を示します。次のような出力が表示される場合があります。

+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
|         21.78 |         80.20 |        100.00 |         100.00 |
+---------------+---------------+---------------+----------------+

これは、文字列の80%が20文字未満であり、すべての文字列が50文字未満であることを示しています。そのため、50のプレフィックス長を超えるインデックスを作成する必要はなく、255文字の全長をインデックス化する必要はありません。

PS:INT(1)およびINT(32)データ型は、MySQLに関する別の誤解を示しています。数値引数は、列に許可されるストレージまたは値の範囲に関連する効果はありません。 INTは常に4バイトで、-2147483648〜2147483647の値を常に許可します。数値引数は、表示中の値のパディングに関するものであり、ZEROFILLオプションを使用しない限り効果はありません。

136
Bill Karwin

このエラーは、インデックスindexの長さが1000バイトを超えることを意味します。 MySQLおよびストレージエンジンにはこの制限がある場合があります。 MySQL 5.5でも同様のエラーが発生しました-'指定されたキーが長すぎました。このスクリプトを実行したときの最大キー長は3072バイトです。

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UTF8はマルチバイトであり、キーの長さはこの方法で計算されます-500 * 3 * 6 = 9000バイト。

ただし、次のクエリは機能します。

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

... CHARSET = latin1を使用したため、この場合、キーの長さは500 * 6 = 3000バイトです。

26
Devart

テーブルを作成または変更する前にこのクエリを実行します。

SET @@global.innodb_large_prefix = 1;

これにより、最大キー長が3072バイトに設定されます

9
Raza Ahmed

私はこの問題を抱えていて、次の方法で解決しました:

原因

MySQLには、ここで確認できるMyISAM、UTF8文字セット、およびインデックスに関連する既知のバグがあります。

解像度

  • MySQLがInnoDBストレージエンジンで構成されていることを確認してください。

  • 新しいテーブルが常に適切に作成されるように、デフォルトで使用されるストレージエンジンを変更します。

    set GLOBAL storage_engine='InnoDb';

  • MySQL 5.6以降では、次を使用します。

    SET GLOBAL default_storage_engine = 'InnoDB';

  • そして最後に、 MySQLへの移行 に記載されている指示に従っていることを確認してください。

参照

6
Vishrant

このインデックスサイズの制限は、MySQLの64ビットビルドでは大きくなるようです。

DevデータベースをダンプしてローカルVMWare virtにロードしようとすると、この制限にぶつかりました。最後に、リモートdevサーバーが64ビットであり、32ビットのvirtを作成したことに気付きました。 64ビットのvirtを作成したばかりで、データベースをローカルにロードできました。

3
Ryan Olson

元のデータベースの「長さ」の値をその構造を変更して合計で約「1000」に変更し、それをサーバーにエクスポートして、このエラーを回避しました。 :)

2

私は同じ問題に直面していましたが、以下のクエリを使用して解決しました。

DBの作成中に、utf-8エンコーディングを使用できます

例えば。 create database my_db character set utf8 collate utf8_bin;

1
Sudhir Dhumal