2012-01-05 33 views
47

このタイトルの質問はこれまでに回答されていますが、お読みください。私は徹底的にこのエラーのすべての他の質問/回答を投稿して投稿しています。私は、次のクエリのために上記のエラーを取得しています#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を使用しています。

答えて

94

@Devartによると、インデックスの全長が長すぎます。

インデックスは非常に大きく、効率が悪いため、このような長いVARCHAR列はインデックスに登録しないでください。

接頭辞インデックスを使用することをお勧めします。これにより、データの左部分文字列のインデックスを作成するだけです。あなたのデータのほとんどは、とにかく255文字よりもずっと短くなります。

インデックスを定義するときに、列ごとに接頭辞の長さを宣言できます。例:

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

ただし、指定した列の最短プレフィックス長はどのくらいですか。ここで見つけるための方法があります:

SELECT 
ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(*),2) AS pct_length_10, 
ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(*),2) AS pct_length_20, 
ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(*),2) AS pct_length_50, 
ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(*),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オプションを使用しない限り無効です。

+6

詳細な説明はありがとうございます。問題を解決することに加えて、私は何か貴重なものを学んだ。 – CodeVirtuoso

+1

これはきちんとしたクエリです。共有してくれてありがとう! – yekta

+0

本当に、インデックスを設定する必要がある長さを見つけるための非常に便利なクエリ。これを使用して、インデックスの最適な長さを決定しています。共有していただきありがとうございます! –

17

このエラーは、インデックスindexの長さが1000バイトを超えていることを意味します。 MySQLとストレージエンジンにはこの制限があります。私はMySQL 5.5上で同様のエラーが発生しました - '指定されたキーが長すぎました。 - 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=utf8; 

UTF8はマルチバイトで、キーの長さは、このように計算されます。このスクリプトを実行したときの最大キー長は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=latin1; 

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

+4

返信ありがとう、これは動作しますが、utf8の文字セットをあきらめてしまいます。この制限を何らかの形で克服できますか(私は完全なサーバーアクセス権を持っています)、良い理由がありますか? – CodeVirtuoso

2

このインデックスサイズの制限は、MySQLの64ビットビルドではもっと大きいようです。

私はdevデータベースをダンプし、ローカルのVMWare virtにロードしようとしています。最後に、私はリモートのdevサーバが64ビットであることを認識し、32ビットのvirtを作成しました。私はちょうど64ビットのvirtを作成し、データベースをローカルにロードすることができました。

5

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

SET @@global.innodb_large_prefix = 1;

これは、私はちょうどちょうど周りに「1000の合計に、元のデータベースでは、「長さ」の値を変更することにより、バイパスこのエラーをした3072バイト

1

への最大の鍵の長さを設定しますその構造を変更して、それをサーバにエクスポートすることで、 :)

関連する問題