InnoDB
テーブルの物理的な行構造は、テーブル作成時に指定された行フォーマットによって異なります。InnoDB
のデフォルトでは、Antelope ファイル形式とその COMPACT
行フォーマットが使用されます。REDUNDANT
形式は、古い MySQL バージョンとの互換性を保つために使用可能です。セクション14.9「InnoDB の行ストレージと行フォーマット」およびセクション14.7「InnoDB 圧縮テーブル」で説明するように、innodb_file_per_table
設定を有効にすると、新しい Barracuda ファイル形式を DYNAMIC
および COMPRESSED
行フォーマットとともに使用することもできます。
InnoDB
テーブルの行フォーマットをチェックするには、SHOW TABLE STATUS
を使用します。例:
mysql> SHOW TABLE STATUS IN test1\G
*************************** 1. row ***************************
Name: t1
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 16384
Data_free: 0
Auto_increment: 1
Create_time: 2014-10-31 16:02:01
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
INFORMATION_SCHEMA.INNODB_SYS_TABLES
でクエリーを実行することで、InnoDB
テーブルの行フォーマットをチェックすることもできます。
mysql> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test1/t1';
+----------+------------+
| NAME | ROW_FORMAT |
+----------+------------+
| test1/t1 | Compact |
+----------+------------+
COMPACT
行フォーマットを使用すると、行のストレージ領域が約 20% 減少しますが、一部の操作では CPU 使用率が高くなります。ワークロードが、キャッシュヒット率とディスク速度によって制限される通常のワークロードであれば、COMPACT
形式が高速になる可能性があります。ワークロードが CPU 速度によって制限されるまれなケースでは、COMPACT
形式が低速になる可能性があります。
REDUNDANT
行フォーマットを使用する InnoDB
テーブル内の行には、次のような特性があります。
各インデックスレコードには、6 バイトのヘッダーが含まれています。このヘッダーは、連続するレコードをリンクするために使用されます。また、行レベルロックでも使用されます。
クラスタ化されたインデックス内のレコードには、すべてのユーザー定義カラムのフィールドが含まれます。さらに、6 バイトのトランザクション ID フィールドと 7 バイトのロールポインタフィールドも含まれています。
テーブルに主キーが定義されなかった場合は、各クラスタ化されたインデックスレコードに 6 バイトの行 ID フィールドも含まれています。
各セカンダリインデックスレコードには、セカンダリインデックス内に存在しないクラスタ化されたインデックスキーに定義されたすべての主キーフィールドも含まれています。
レコードには、そのレコードの各フィールドへのポインタが含まれます。レコード内のフィールド長の合計が 128 バイト未満の場合はポインタが 1 バイト、128 バイト以上の場合はポインタが 2 バイトになります。これらのポインタの配列はレコードディレクトリと呼ばれます。これらのポインタが示す領域は、レコードのデータ部分と呼ばれます。
InnoDB
には内部的に、固定長形式のCHAR(10)
などの固定長文字カラムが格納されます。InnoDB
は、VARCHAR
カラム内の末尾の空白を切り捨てません。SQL の
NULL
値では、レコードディレクトリに 1 バイトまたは 2 バイトが予約されます。それ以外に、SQL のNULL
値では、可変長カラム内に格納されるとレコードのデータ部分にゼロバイトが予約されます。固定長カラムでは、レコードのデータ部分内にカラムの固定長が予約されます。NULL
値用に固定領域を予約すると、インデックスページの断片化が発生せずに、カラムをNULL
から非NULL
値に更新できます。
COMPACT
行フォーマットを使用する InnoDB
テーブル内の行には、次のような特性があります。
各インデックスレコードには、前に可変長ヘッダーが付く可能性のある 5 バイトのヘッダーが含まれています。このヘッダーは、連続するレコードをリンクするために使用されます。また、行レベルロックでも使用されます。
レコードヘッダーの可変長部分には、
NULL
カラムを示すビットベクトルが含まれています。NULL
にすることができるインデックス内のカラム数がN
である場合は、ビットベクトルでCEILING(
バイトが占有されます。(たとえば、N
/8)NULL
にすることができるカラムが 9 から 15 までの任意の数だけ存在する場合は、ビットベクトルで 2 バイトが使用されます。)このベクトル内のビット以外の領域は、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-8CHAR(
カラムをN
)N
バイトで格納しようとします。(REDUNDANT
行フォーマットでは、このようなカラムで 3 ×N
バイトが占有されます。)多くの場合は、最小領域N
を予約すると、インデックスページの断片化が発生せずに、カラムの更新を正常に実行できます。