InnoDB
テーブルの行の物理構造は、テーブル作成時に指定された行形式によって異なります。MySQL5.1
ではデフォルトで
InnoDB
が
COMPACT
フォーマットを利用しますが、MySQL
の古いバージョンとの互換性を保持するためには
REDUNDANT
フォーマットが有効です。InnoDB
テーブルの行形式を確認するには、SHOW
TABLE STATUS
を使用します。
コンパクト行形式を使えば行のストレージ容量を約 20% 削減できますが、その代わり一部の処理で CPU 使用率が上がります。作業負荷が、キャッシュのヒット率やディスクの速度によって制限される典型的なものであれば、コンパクト形式のほうがおそらく高速になります。作業負荷が CPU 速度によって制限されるというレアケースの場合は、コンパクト形式のほうが低速になる可能性があります。
REDUNDANT
行形式を使用する
InnoDB
テーブル内の行には、次のような特性があります。
各インデックスレコードは 6 バイトのヘッダーを含んでいます。このヘッダーは、連続するレコードをリンクするためと、行レベルロックで使用されます。
クラスタインデックス内のレコードには、すべてのユーザー定義カラムのフィールドが含まれます。さらに、6 バイトのトランザクション ID フィールドと 7 バイトのロールポインタフィールドも存在しています。
ユーザーがテーブルに主キーを定義していない場合は、クラスタインデックスの各レコードは 6 バイトの行 ID フィールドも含みます。
各二次インデックスレコードには、二次インデックス内に存在しないクラスタインデックスキー用に定義されたすべての主キーフィールドが格納されます。
レコードには、そのレコードの各フィールドへのポインタが含まれます。レコード内のフィールド長の合計が 128 バイト未満の場合はポインタが 1 バイト、128 バイト以上の場合はポインタが 2 バイトになります。これらのポインタの配列はレコードディレクトリと呼ばれます。これらのポインタが指し示すエリアはレコードのデータ部分と呼ばれます。
InnoDB
は内部的に固定長フォーマットの
CHAR(10)
のような固定長文字カラムを格納します。InnoDB
は、VARCHAR
カラム内の末尾の空白を切り詰めません。
SQLNULL
値はレコードディレクトリに 1 バイトか 2
バイトを蓄えておきます。それ以外に、SQL
NULL
値は可変長カラム内に格納されるとレコードのデータ部分にゼロバイトを蓄えます。それは固定長カラム内でレコードのデータ部分内にカラムの固定長を蓄えます。NULL
値に固定領域を蓄えれば、インデックスページの崩壊を起こさずに、カラムを
NULL
から非
NULL
値に更新することができます。
COMPACT
行形式を使用する
InnoDB
テーブル内の行には、次のような特性があります。
各インデックスレコードは可変長ヘッダーに先導される 5 バイトのヘッダーを含んでいます。このヘッダーは、連続するレコードをリンクするためと、行レベルロックで使用されます。
レコードヘッダーの可変長部分には、NULL
カラムを示すためのビットベクトルが格納されます。NULL
の可能性のあるインデックス内のカラム数が
N
の場合、ビットベクトルは
(N
+7)/8
バイトを占有します。NULL
カラムがこのベクタ内のビット以外の領域を占めることはありません。ヘッダーの可変長部分には可変長カラムの長さも格納されます。各長さのサイズは、カラムの最大長に応じて
1 バイト、2
バイトのいずれかになります。インデックス内のすべてのカラムが
NOT NULL
でかつ固定長である場合、レコードヘッダーには可変長部分が一切含まれません。
各非 NULL
可変長フィールドに対して、レコードヘッダーは
1 か 2
バイトのカラム長を含みます。カラムの一部が外部のオーバーフローページに格納されたり、最大長が
255 バイトを超える、または実際の長さが 127
バイトを超えたりしなければ 2
バイトだけ必要になります。外部に格納されるカラムの場合、この
2
バイトの長さは、内部に格納された部分の長さと外部に格納された部分への
20
バイトのポインタの長さの合計を示します。内部部分は
768 バイトなので、長さは 768+20
になります。20
バイトのポインタには、そのカラムの実際の長さが格納されます。
レコードヘッダーのあとに、非
NULL
カラムのデータ内容が続きます。
クラスタインデックス内のレコードには、すべてのユーザー定義カラムのフィールドが含まれます。さらに、6 バイトのトランザクション ID フィールドと 7 バイトのロールポインタフィールドも存在しています。
ユーザーがテーブルに主キーを定義していない場合は、クラスタインデックスの各レコードは 6 バイトの行 ID フィールドも含みます。
各二次インデックスレコードには、二次インデックス内に存在しないクラスタインデックスキー用に定義されたすべての主キーフィールドが格納されます。これらの主キーフィールドのいずれかが可変長である場合、各二次インデックスのレコードヘッダーには、その二次インデックスが固定長カラムで定義されたものであったとしても、それらのフィールドの長さを記録するための可変長部分が含まれます。
InnoDB
は内部的に固定長フォーマットの
CHAR(10)
のような固定長、固定幅文字カラムを格納します。InnoDB
は、VARCHAR
カラム内の末尾の空白を切り詰めません。
InnoDB
は、後続領域を切り取ることで内部的に UTF-8
CHAR(
カラムを N
)N
バイトで格納しようとします。(REDUNDANT
行形式ではそのようなカラムは 3 ×
N
バイトを占有する。)
最小領域 N
を確保すれば多くの場合、インデックスページの断片化を発生させずにカラムの更新を行えます。