21

エラー:

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

CREATE TABLE `phppos_modules_actions` (
  `action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `sort` INT NOT NULL ,
  PRIMARY KEY ( `action_id` , `module_id` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

255x2x3(1文字あたり3バイト)が原因でエラーが発生することはわかっています

これは、すべてのインストールで発生するわけではありません。どの設定を変更できますか?

4

9 に答える 9

15

NO_ENGINE_SUBSTITUTIONが無効になっていて、INNODBがアクティブではない、悪い組み合わせ

  • MySql 5.5までは、sqlmodeのデフォルトは空白の文字列でした。つまり、sqlmodeNO_ENGINE_SUBSTITUTIONはデフォルトで設定されていませんでした。

MySqlのドキュメント(https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_no_engine_substitutionを参照)によると、これはsqlmodeNO_ENGINE_SUBSTITUTIONの意味です。

CREATETABLEやALTERTABLEなどのステートメントで、で無効になっている、またはコンパイルされていないストレージエンジンが指定されている場合は、デフォルトのストレージエンジンの自動置換を制御します。

ストレージエンジンは実行時にプラグイン可能である可能性があるため、使用できないエンジンは同じように扱われます。

NO_ENGINE_SUBSTITUTIONを無効にすると、CREATE TABLEではデフォルトのエンジンが使用され、目的のエンジンが使用できない場合は警告が表示されます。ALTER TABLEの場合、警告が発生し、テーブルは変更されません。

NO_ENGINE_SUBSTITUTIONを有効にすると、エラーが発生し、目的のエンジンが使用できない場合、テーブルは作成または変更されません。

  • したがって、NO_ENGINE_SUBSTITUTIONが無効で、INNODBがオフになっている場合、CREATE TABLEステートメントでINNODBを指定した場合も、MySqlはMYISAMに切り替わります。
  • 作成しているテーブルがMYISAMで問題ない場合は、警告が表示され、テーブルが作成されます。そうではありません。作成ステートメントにMYISAMの1000バイトの制限を超えるインデックスが含まれていると、作成が失敗し、エラー1071でMYISAMのエラーが報告されます。これは、動作するエンジンがINNODBではなくMYISAMであるためです。

証拠

MySqlバージョン5.1.56コミュニティ

ケース1:

Options in my.cnf  
sql-mode=""  
default-storage-engine=MYISAM  
skip-innodb uncommented (without#) 

Return on execution of your create statement:
Error Code: 1071. Specified key was too long; max key length is 1000 bytes

Explanation: INNODB is not active, the engine is automatically switched to MYISAM  
that returns this error as they key is longer than MYISAM 1000 bytes limit.  
The key length is: 
2 fields x 255 char x 3 bytes utf8 encoding + 2 x 1 length byte = 1532 bytes   

ケース2:

Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb uncommented (without#)

Return on execution of your create statement:
Error Code: 1286. Unknown table engine 'INNODB'

Explanation: INNODB is not active but the engine substitution is not permitted
by sql mode therefore the DB returns an error about the attempt of using a disabled engine. 

ケース3:

Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb commented (with#)

Return on execution of your create statement:
Table creation OK!

Explanation: INNODB is active (skip-innodb commented) and it is used also if      
the default engine is MYISAM.

テストを再現するには、my.cnfを変更するたびにMySqlを再起動します。

MySqlバージョン5.6sqlmodeはデフォルトで空ではなくなり、NO_ENGINE_SUBSTITUTIONが含まれているため、さらにINNODBがデフォルトのエンジンであるため、エラーを検出するのは困難です。

その他のテスト

エラーを再現する他の方法はありません:

Error Code: 1071. Specified key was too long; max key length is 1000 bytes 

INNODBテーブルを作成しようとしているときに見つかりました。

INNODBには、2種類のエラー1071があります。

Error Code: 1071. Specified key was too long; max key length is 767 bytes

これは、innodb_large_prefixのONまたはOFFとは関係ありませんが、インデックスとして使用されている単一のVARCHAR列のサイズにのみ関係します。

Mysqlはvarcharutf8を3バイトに加えて255文字までの長さで1バイト、その後に2バイトを格納します(http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.htmlを参照)。次のようなVARCHAR(256)utf8でキーを設定してみてください。

256 x 3 + 2 = 770 bytes

InnoDBテーブルの単一列の最大キー長は767バイトであるため、前のエラーが発生します。VARCHAR(255)は、次の理由で問題ありません。

255 x 3 + 1 = 766 bytes

Mysqlの4つのインストール、バージョン5.1.56、5.5.33、5.6、および5.7でテストしましたが、それが確認されています。VARCHAR(255)でのクエリ、VARCHAR(256)での問題はありません。

Error Code: 1071. Specified key was too long; max key length is 767 bytes

ご覧のとおり、メッセージはMYISAMではなくINNODBメッセージであるため、異なります。

INNODBテーブルのその他のタイプのERROR1071は次のとおりです。

Error Code: 1071. Specified key was too long; max key length is 3072 bytes

これは、複数の列を持つキーに関連しています。これらのキーを有効にするには、innodb_large_prefixをonに設定する必要があります。とにかく、あなたがこのような何かを実行しようとすると:

CREATE TABLE `phppos_modules_actions` (
  `action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key1` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key2` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `sort` INT NOT NULL ,
  PRIMARY KEY ( `action_id` , `module_id`, `action_name_key`, `action_name_key1`, `action_name_key2` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

5つのVARCHAR(255)utf8列のキー(3830バイト)を使用すると、次のようになります。

Error Code: 1071. Specified key was too long; max key length is 3072 bytes

エキゾチックな仮説

原因の調査中に、私はさまざまでかなり奇妙な仮説を立ててテストしました。

ROW形式

テスト済みの冗長、コンパクト、圧縮、動的:ステートメントによるテーブル作成への影響​​はありません。

ファイル形式

テスト済みのアンテロープとバラクーダ:ステートメントによるテーブル作成への影響​​はありません。

MySqlが構築されました

テスト済みの32ビットおよび64ビットのMySql:ステートメントによるテーブル作成への影響​​はありません。

他の同様の失敗

ここでは、同じ状況で同じエラーを見つけることができます。

https://www.drupal.org/node/2466287

私はPROOFにリストされている3つのテスト状況でそのステートメントをテストしましたが、それはあなたとまったく同じ動作を再現したので、問題は同じであると言えます。その場合、他のDBに切り替えましたが、問題はDBバージョンではなく、設定の組み合わせです。

参考文献

INNODBを使用したインデックス作成の非常に優れた記事がここにあります。

http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/

警告:インデックスが1000より長いINNODBテーブルを作成した後、my.cnfでskip-innodbのコメントを解除してINNODBを無効にすると、MySqlサービスの開始が許可されません。

よろしく

于 2016-03-18T17:39:47.543 に答える
3

私は今あなたがどれほどの柔軟性を持っているかはわかりませんが、ここにいくつかのオプションがあります:

  • MySQLバージョンを最新リリースにアップグレードします(MySQL 5.5.25でコードをテストしましたが、エラーは発生しませんでした)。

  • utf8からlatin1に変更します。

  • 主キーを構成するフィールドのサイズを縮小します。別のauto_increment主キーフィールドを作成して、既存のキーを置き換えます。最初のフィールドに別のインデックスを作成しますaction_id (ただし、2番目のフィールドは作成しません)

これらのオプションを除いて、1000バイトを超えるインデックスキーを有効にするMySQLで変更できる設定がないため、ほとんど行き詰まっています。

于 2012-08-07T17:00:50.940 に答える
3

MySQL 5.6.3+では、いくつかの制限(、、ROW_FORMAT=DYNAMICおよびinnodb_file_format=BARRACUDA)があり、3072バイトのキー長制限innodb_file_per_table=trueを有効にできます。innodb_large_prefix

于 2016-03-16T18:34:15.367 に答える
2

あなたは(偶然に?)InnoDBをオフにしました。MyISAMとしてテーブルを作成しており、キー全体が1000バイトを超えています。

InnoDBがあるかどうか、および「no_engine_substitution」があるかどうかの変数を確認します(5.1.56に存在していた場合)。またmysqld.err、起動時に関連するエラーがあるかどうかを確認します。

于 2016-03-22T00:22:56.903 に答える
1

ストレージエンジンに関連しているようです。私のエンドユーザーはMyISAM、データのストレージを異なる方法で処理するを使用していたため、そのエラーが発生しました。

于 2016-03-16T18:13:38.570 に答える
1

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

VARCHAR簡単な答えは、インデックスが非常にかさばり、非効率になるため、とにかくそのような長い列にインデックスを付けるべきではないということです。

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

767バイトは、テーブルのプレフィックス制限として規定されています。テーブルInnoDBの長さは1,000バイトですMyISAM

この問題への対応によると、全額ではなく列のサブセットを指定することで、適用するキーを取得できます。手段インデックスを定義するときに、列ごとのプレフィックス長を宣言できます。

例えば:

KEY `key_name` (`action_id`(50),`module_id`(50))

これをより明確に説明する例を次に示します。テーブルを作成し、それにいくつかのデータを挿入しました。

CREATE TABLE `phppos_modules_actions` (
  `action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `sort` INT NOT NULL ,
  PRIMARY KEY ( `action_id`(50) , `module_id`(50) )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

しかし、特定の列に最適なプレフィックスの長さはどれくらいですか?調べる方法は次のとおりです。

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


+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
|         42.86 |         80.20 |        100    |         100    |
+---------------+---------------+---------------+----------------+

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

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

innodbの設定に関する別の方法は、http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/にあります。

于 2016-03-22T05:32:34.663 に答える
0

公式ドキュメント5.6

InnoDBテーブルの制限

InnoDBの内部最大キー長は3500バイトですが、MySQL自体はこれを3072バイトに制限しています。この制限は、複数列の索引の複合索引キーの長さに適用されます。

http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html


MyISAMストレージエンジン

キーの最大長は1000バイトです。これは、ソースを変更して再コンパイルすることによっても変更できます。250バイトより長いキーの場合、デフォルトの1024バイトよりも大きいキーブロックサイズが使用されます。

http://dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html


ただし、テーブルはInnoDBとして宣言されています。だから私は何を考えるべきかわからない

この古いバグの終わりにも手がかりがあります

これが必要な場合は、MySQL 5.5と、5.5.14(2011年7月)以降に利用できるinnodb_large_prefixオプションを実際に確認する必要があります。これは、おそらく探していることを実行するためです。

"このオプションを有効にすると、DYNAMICおよびCOMPRESSED行フォーマットを使用するInnoDBテーブルの767バイトより長い(最大3072バイト)インデックスキープレフィックスが許可されます(このようなテーブルを作成するには、オプション値innodb_file_format=barracudaおよびinnodb_file_per_table=trueも必要です)。さまざまな設定でのインデックスキープレフィックスに関連する最大値については、13.3.15項「InnoDBテーブルの制限」を参照してください。

于 2016-03-17T21:50:37.647 に答える
0

キーの最大長は1000バイトです。これは、ソースを変更して再コンパイルすることによっても変更できます。250バイトより長いキーの場合、デフォルトの1024バイトよりも大きいキーブロックサイズが使用されます。

于 2016-03-20T12:16:41.747 に答える
0

私の場合、MySQLはInnoDBのサポートなしで起動されました。また、DBバックアップのインポート中に-MyISAMテーブルを作成しようとしました。

同時に、MySQLの再起動中にコンソールにエラーは表示されませんでした。
MySQLログファイルをチェックした場合のみ-これが見つかりました。

ところで、エラーはinnodb_log_file_size = 4Gに変更された場合にのみ関連していましたinnodb_log_file_size = 1G-InnoDBサポートが有効になりました。

于 2018-05-24T12:06:55.917 に答える