このタイトルの質問には以前に回答したことがありますが、読んでください。投稿する前に、このエラーに関する他の質問/回答をすべて読みました。
次のクエリで上記のエラーが発生しています。
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を使用しています。
@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
オプションを使用しない限り効果はありません。
このエラーは、インデックス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バイトです。
テーブルを作成または変更する前にこのクエリを実行します。
SET @@global.innodb_large_prefix = 1;
これにより、最大キー長が3072バイトに設定されます
私はこの問題を抱えていて、次の方法で解決しました:
原因
MySQLには、ここで確認できるMyISAM、UTF8文字セット、およびインデックスに関連する既知のバグがあります。
解像度
MySQLがInnoDBストレージエンジンで構成されていることを確認してください。
新しいテーブルが常に適切に作成されるように、デフォルトで使用されるストレージエンジンを変更します。
set GLOBAL storage_engine='InnoDb';
MySQL 5.6以降では、次を使用します。
SET GLOBAL default_storage_engine = 'InnoDB';
そして最後に、 MySQLへの移行 に記載されている指示に従っていることを確認してください。
このインデックスサイズの制限は、MySQLの64ビットビルドでは大きくなるようです。
DevデータベースをダンプしてローカルVMWare virtにロードしようとすると、この制限にぶつかりました。最後に、リモートdevサーバーが64ビットであり、32ビットのvirtを作成したことに気付きました。 64ビットのvirtを作成したばかりで、データベースをローカルにロードできました。
元のデータベースの「長さ」の値をその構造を変更して合計で約「1000」に変更し、それをサーバーにエクスポートして、このエラーを回避しました。 :)
私は同じ問題に直面していましたが、以下のクエリを使用して解決しました。
DBの作成中に、utf-8エンコーディングを使用できます
例えば。 create database my_db character set utf8 collate utf8_bin;