Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
EPUB - 7.5Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


14.6.7 InnoDB テーブル上の制限

警告

mysql データベース内の MySQL システムテーブルを MyISAM から InnoDB テーブルに変換しないでください。これはサポートされていない操作です。これを行うと、mysql_install_db プログラムを使用してバックアップから古いシステムテーブルをリストアするか、再生成するまで、MySQL は再起動されません。

警告

NFS ボリューム上でデータファイルやログファイルが使用されるように InnoDB を構成することは、適切ではありません。それ以外の場合は、ファイルがほかのプロセスによってロックされ、MySQL で使用できなくなる可能性があります。

最大と最小

  • テーブルには、最大で 1017 個のカラムを含めることができます (MySQL 5.6.9 で、以前の 1000 個の制限から上昇されました)。

  • テーブルには、最大で 64 個のセカンダリインデックスを含めることができます。

  • デフォルトでは、単一カラムインデックスのインデックスキーを最大で 767 バイトにすることができます。インデックスキープリフィクスにも同じ長さ制限が適用されます。セクション13.1.13「CREATE INDEX 構文」を参照してください。たとえば、UTF-8 文字セットと文字ごとに最大 3 バイトを使用すると仮定すれば、TEXT または VARCHAR カラム上で 255 文字よりも長いカラムプリフィクスインデックスを使用すると、この制限に達する可能性があります。innodb_large_prefix 構成オプションを有効にすると、DYNAMIC および COMPRESSED 行フォーマットを使用する InnoDB テーブルで、この長さ制限が 3072 バイトに上昇します。

    許可されている最大値よりも長いインデックスプリフィクス長を使用しようとすると、エラーが生成されます。スレーブ上でも innodb_large_prefix オプションを設定できなく、この制限の影響を受ける可能性のある一意のインデックスをスレーブが持っている場合は、レプリケーション構成でこのようなエラーを回避するために、このオプションをマスター上で設定することを避けてください。

  • InnoDB の内部的な最大キー長は 3500 バイトですが、MySQL 自体では 3072 バイトに制限されています。この制限は、複数カラムインデックス内の結合されたインデックスキーの長さに適用されます。

  • MySQL インスタンスの作成時に innodb_page_size オプションを指定して、InnoDBページサイズを 8K バイトまたは 4K バイトまで小さくすると、16K バイトのページサイズに対応する 3072 バイトの制限に基づいて、比例的にインデックスキーの最大長も短くなります。つまり、インデックスキーの最大長は、ページサイズが 8K バイトのときは 1536 バイト、ページサイズが 4K バイトのときは 768 バイトになります。

  • 可変長カラム (VARBINARYVARCHARBLOB、および TEXT) を除き、行の最大長はデータベースページの半分より少し短くなります。つまり、デフォルトページサイズの 16K バイトでは、行の最大長が約 8000 バイトになります。MySQL インスタンスの作成時に innodb_page_size オプションを指定してページサイズを小さくすると、行の最大長は、8K バイトのページでは 4000 バイト、4K バイトのページでは 2000 バイトになります。LONGBLOB および LONGTEXT カラムは 4G バイト未満である必要があり、BLOB および TEXT カラムを含む行全体の長さは 4G バイト未満である必要があります。

    行の長さが 1 ページの半分より短い場合は、行全体がそのページ内にローカルに格納されます。セクション14.10.2「ファイル領域管理」で説明したように、半ページを超える行では、その行が半ページ以内に収まるように、可変長カラムが外部オフページストレージの対象として選択されます。

  • InnoDB では内部的に 65,535 バイトを超える行サイズがサポートされていますが、MySQL 自体では、すべてのカラムを結合したサイズに 65,535 行のサイズ制限が課されています。

    mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
        -> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
        -> f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
    ERROR 1118 (42000): Row size too large. The maximum row size for the
    used table type, not counting BLOBs, is 65535. You have to change some
    columns to TEXT or BLOBs
    

    セクションD.10.4「テーブルカラム数と行サイズの制限」を参照してください。

  • 一部の古いオペレーティングシステムでは、ファイルは 2G バイトよりも小さくする必要があります。これは、InnoDB 自体の制限ではありません。ただし、大きいテーブルスペースが必要な場合は、1 つではなく複数の小さいデータファイルを使用して構成するか、より大きいデータファイルを作成する必要があります。

  • InnoDB ログファイルを結合したサイズは、最大で 512G バイトまでにすることができます。

  • テーブルスペースの最小サイズは、10M バイトをわずかに超える大きさです。テーブルスペースの最大サイズは、40 億データベースページ (64T バイト) です。これはテーブルの最大サイズでもあります。

  • InnoDB のデフォルトのデータベースページサイズは 16K バイトですが、MySQL インスタンスの作成時に innodb_page_size オプションを指定すれば、ページサイズを 8K バイトまたは 4K バイトまで小さくすることができます。

    注記

    ページサイズを大きくすることは、サポートされている操作ではありません。InnoDB では、16K バイトを超えるページサイズでは通常な動作が保証されません。InnoDB をコンパイルまたは実行するときに、問題が発生する可能性があります。特に、Barracuda ファイル形式の ROW_FORMAT=COMPRESSED では、ページサイズが 16K バイトで、14 ビットのポインタを使用することが前提となっています。

    特定の InnoDB ページサイズを使用している MySQL インスタンスは、別のページサイズを使用するインスタンスのデータファイルやログファイルを使用できません。この制限によって、16K バイト以外のページサイズがサポートされている MySQL 5.6 のデータを使用したリストアまたはダウングレード操作が影響を受ける可能性があります。

インデックスの型

  • MySQL 5.6.4 以降では、InnoDB テーブルで FULLTEXT インデックスがサポートされています。詳細は、セクション14.2.13.3「FULLTEXT インデックス」を参照してください。

  • InnoDB テーブルでは空間データ型がサポートされますが、そのインデックスはサポートされません。

InnoDB テーブル上の制約

  • 各インデックスツリーにランダムダイブを行い、それに従ってインデックスカーディナリティーの見積もりを更新すると、(SHOW INDEX 出力の「Cardinality」カラムに表示されるように) ANALYZE TABLE でインデックスカーディナリティーが決定されます。これらは単なる見積もりであるため、ANALYZE TABLE を繰り返し実行すると、別の数値が生成される可能性があります。これによって ANALYZE TABLEInnoDB テーブル上での速度は速くなりますが、すべての行が考慮されているわけではないため、100% 正確とは言えません。

    セクション14.13.16.1「永続的オプティマイザ統計のパラメータの構成」で説明したように、innodb_stats_persistent 構成オプションをオンにすると、ANALYZE TABLE で収集された統計の正確性および安定性を向上させることができます。統計は定期的に再計算されないため、この設定を有効にした場合は、従来と同様に、インデックス付きカラムデータの主要な変更後 (サーバーの再起動後など) に、ANALYZE TABLE を実行することが重要です。

    innodb_stats_persistent_sample_pages システム変数 (永続的な統計設定がオンになっている場合)、または innodb_stats_transient_sample_pages システム変数 (永続的な統計設定がオフになっている場合) を変更すると、ランダムダイブの数を変更できます。

    MySQL では、結合の最適化時にのみインデックスカーディナリティーの見積もりが使用されます。一部の結合が適切に最適化されない場合は、ANALYZE TABLE を使用してみてください。ANALYZE TABLE では特定のテーブルに十分な値が生成されない場合は、特定のインデックスの使用を強制するクエリーとともに FORCE INDEX を使用するか、または MySQL でテーブルスキャンよりもインデックス検索が優先されるように max_seeks_for_key システム変数を設定してください。セクション5.1.4「サーバーシステム変数」、およびセクションB.5.6「オプティマイザ関連の問題」を参照してください。

  • テーブル上でステートメントまたはトランザクションが実行されていて、ANALYZE TABLE のあとに同じテーブル上で 2 番目の ANALYZE TABLE 操作が実行されると、そのステートメントまたはトランザクションが完了するまで、2 番目の ANALYZE TABLE 操作はブロックされます。この動作が発生する原因は、ANALYZE TABLE の実行が完了すると、ANALYZE TABLE によって現在ロード中のテーブル定義に非推奨のマークが付けられるためです。新しいステートメントまたはトランザクション (2 番目の ANALYZE TABLE ステートメントを含む) は、新しいテーブル定義をテーブルキャッシュにロードする必要があります。この動作は、現在実行中のステートメントまたはトランザクションが完了し、古いテーブル定義がパージされるまで発生する可能性がありません。複数の並列テーブル定義をロードすることは、サポートされていません。

  • SHOW TABLE STATUS では、テーブルで予約された物理サイズを除き、InnoDB テーブルに関する正確な統計が得られません。行カウントは、単に SQL 最適化で使用される概算見積もりです。

  • 並列トランザクションでは同時にさまざまな数の行が参照される可能性があるため、InnoDB のテーブルには、行の内部的なカウントが保持されません。SELECT COUNT(*) FROM t ステートメントを処理するために、InnoDB ではテーブルのインデックスがスキャンされますが、インデックスが完全にバッファープール内にない場合は多少時間がかかります。テーブルが頻繁に変更されない場合は、MySQL クエリーキャッシュを使用することが適切な解決策となります。すばやくカウントするには、自分で作成したカウンタテーブルを使用し、実行される挿入および削除に応じてアプリケーションで更新できるようにする必要があります。概算の行カウントでは十分でない場合は、SHOW TABLE STATUS を使用できます。セクション8.5「InnoDB テーブルの最適化」を参照してください。

  • Windows 上の InnoDB では常に、データベース名およびテーブル名が内部的に小文字で格納されます。バイナリ形式のデータベースを Unix から Windows に、または Windows から Unix に移動するには、すべてのデータベースおよびテーブルを小文字の名前を使用して作成します。

  • 最大カラム値を取得するためにテーブルでのインデックス付きの SELECT MAX(ai_col) 検索と同等の操作を実行できるように、AUTO_INCREMENT カラム ai_col をインデックスの一部として定義する必要があります。一般に、これはカラムをどこかのテーブルインデックスの 1 番目のカラムにすることで実現されます。

  • InnoDB は、テーブル上に事前に指定された AUTO_INCREMENT カラムの初期化中に、AUTO_INCREMENT カラムに関連付けられたインデックスの最後に排他ロックを設定します。自動インクリメントカウンタにアクセスするときに InnoDB では、トランザクション全体の最後までではなく、現在の SQL ステートメントの最後まで存続する特別な AUTO-INC テーブルロックモードが使用されます。AUTO-INC テーブルロックが保持されている間は、ほかのクライアントはそのテーブルに挿入できません。セクション14.6.5「InnoDB での AUTO_INCREMENT 処理」を参照してください。

  • MySQL サーバーを再起動すると、AUTO_INCREMENT カラム用に生成されたが一度も格納されなかった古い値 (つまり、ロールバックされた古いトランザクション内で生成された値) が InnoDB で再使用される可能性があります。

  • AUTO_INCREMENT 整数カラムの値を使い果たすと、後続の INSERT 操作で重複キーエラーが返されます。これは一般的な MySQL の動作であり、MyISAM の動作と似ています。

  • DELETE FROM tbl_name はテーブルを再生成しませんが、その代わりにすべての行を 1 つずつ削除します。

  • 現在、カスケードされた外部キーのアクションではトリガーがアクティブになっていません。

  • 内部 InnoDB カラム (DB_ROW_IDDB_TRX_IDDB_ROLL_PTRDB_MIX_ID など) の名前と一致するカラム名を持つテーブルを作成することはできません。サーバーはエラー 1005 をレポートし、エラーメッセージ内のエラー −1 を参照します。この制約は、大文字の名前を使用する場合にのみ適用されます。

ロックとトランザクション

  • innodb_table_locks=1 (デフォルト) の場合、LOCK TABLES で各テーブル上に 2 つのロックが取得されます。MySQL レイヤーでのテーブルロックに加えて、InnoDB テーブルロックも取得されます。バージョン 4.1.2 よりも前の MySQL では、InnoDB テーブルロックが取得されませんでした。この古い動作は、innodb_table_locks=0 を設定すれば選択できます。InnoDB テーブルロックが取得されない場合は、テーブルの一部のレコードがほかのトランザクションによってロックされなくても、LOCK TABLES が完了します。

    MySQL 5.6 では、LOCK TABLES ... WRITE を使用して明示的にロックされたテーブルには、innodb_table_locks=0 が無効です。LOCK TABLES ... WRITE で暗黙的に (たとえば、トリガーを使用して)、または LOCK TABLES ... READ によって、読み取りまたは書き込み用にロックされたテーブルには有効です。

  • トランザクションで保持されているすべての InnoDB ロックは、トランザクションがコミットまたは中止されると解放されます。したがって、autocommit=1 モードの InnoDB テーブル上で LOCK TABLES を呼び出しても、取得された InnoDB テーブルロックはすぐに解放されてしまうため、まったく意味がありません。

  • LOCK TABLES では暗黙的な COMMIT および UNLOCK TABLES が実行されるため、トランザクションの実行中に追加のテーブルをロックできません。

  • 並列データ変更トランザクションの 1023 個の制限は、MySQL 5.5 以上で上昇されました。現在、その制限は、Undo レコードが生成される 128 * 1023 個の並列トランザクションになりました。適切なトランザクション構造を変更する必要のある回避策 (より頻繁にコミットするなど) をすべて解除できます。


User Comments
Sign Up Login You must be logged in to post a comment.