MEMORY
ストレージエンジン (従来は HEAP
と呼ばれていました) は、メモリーに格納された内容で特定用途のテーブルを作成します。 データは、クラッシュ、ハードウェア問題、または電源停止に弱いため、これらのテーブルは、一時的な作業領域またはほかのテーブルから抽出されたデータの読み取り専用キャッシュとして使用されるだけです。
表 16.4 「MEMORY ストレージエンジンの機能」
機能 | Support |
---|---|
B ツリーインデックス | はい |
MVCC | いいえ |
T ツリーインデックス | いいえ |
インデックスキャッシュ | N/A |
クラスタデータベースのサポート | いいえ |
クラスタ化されたインデックス | いいえ |
ストレージの制限 | RAM |
データキャッシュ | N/A |
データディクショナリ向け更新統計 | はい |
トランザクション | いいえ |
ハッシュインデックス | はい |
バックアップ/ポイントインタイムリカバリ (ストレージエンジン内ではなくサーバー内で実装されています。) | はい |
レプリケーションのサポート (ストレージエンジン内ではなくサーバー内で実装されています。) | 制限付き (このセクションの後半の説明を参照してください。) |
ロック粒度 | Table |
全文検索インデックス | いいえ |
圧縮データ | いいえ |
地理空間インデックスのサポート | いいえ |
地理空間データ型のサポート | いいえ |
外部キーのサポート | いいえ |
暗号化データ | はい (暗号化機能を介してサーバーに実装されます。) |
重要で可用性の高い、または頻繁に更新されるデータのために MEMORY
ストレージエンジンを使用するアプリケーションを配備する開発者は、NDB Cluster の方がよいかどうかを考慮するようにしてください。 MEMORY
エンジンの典型的なユースケースには、次の特徴があります。
セッション管理やキャッシングなどの一時的で重要でないデータに関連する操作。 MySQL サーバーが停止または再起動したときに、
MEMORY
テーブルのデータは失われます。高速アクセスおよび低待機時間のためのインメモリー保存。 データボリュームはメモリー内に完全に収まり、オペレーティングシステムによる仮想メモリーページのスワップアウトはありません。
読み取り専用または読み取りが大半のデータのアクセスパターン (更新が制限されています)。
NDB Cluster は、より高いパフォーマンスレベルの MEMORY
エンジンと同じ機能を提供し、MEMORY
では使用できない追加機能を提供します:
クライアント間で競合の少ない行レベルロックとマルチスレッド操作。
書き込みを含むステートメント混在時の拡張性。
データ持続性のためのディスクバックアップ式操作 (オプション)。
単一障害点がない、シェアードナッシングアーキテクチャーと複数ホスト操作。99.999% の可用性を実現できます。
ノードをまたがる自動データ分散。アプリケーションの開発者はカスタムの共有またはパーティション化ソリューションを作る必要がありません。
可変長データ型 (
MEMORY
がサポートしないBLOB
およびTEXT
を含みます) をサポートします。
MEMORY
のパフォーマンスは、更新処理時のシングルスレッド実行とテーブルロックオーバーヘッドが原因の競合によって抑制されます。 このため、負荷が増えたときに拡張性が制限されます (特に、書き込みを含むステートメント混在時)。
MEMORY
テーブルのインメモリー処理にかかわらず、それらは、汎用目的クエリーのために、または読み取り/書き込み負荷では、必ずしもビジーサーバーの InnoDB
テーブルより高速である必要はありません。 特に、更新実行に関与するテーブルロックは、複数セッションからの MEMORY
テーブルの並列使用の速度を低下させる可能性があります。
MEMORY
テーブルで実行されるクエリーの種類によっては、デフォルトのハッシュデータ構造 (一意キーで 1 つの値を検索する場合)、または汎用目的の B ツリーデータ構造 (等号、不等号、未満または「- を超える」などの範囲演算子などを含むすべての種類のクエリーの場合) のいずれかとしてインデックスを作成する場合があります。 次のセクションでは、両方の種類のインデックスを作成するための構文について説明します。 パフォーマンス面でよくある問題は、B ツリーインデックスがより効率的な作業負荷で、デフォルトのハッシュインデックスを使用していることです。
MEMORY
ストレージエンジンは、ディスク上にファイルを作成しません。 テーブル定義は、MySQL データディクショナリに格納されます。
MEMORY
テーブルには次のような特徴があります。
MEMORY
テーブルの領域は小さなブロックに割り当てられます。 テーブルは、挿入に 100% 動的ハッシュを使用します。 オーバーフロー領域や余分なキー領域は必要ありません。 フリーリスト用の余分な領域は必要ありません。 削除された行はリンクリストに置かれ、新しいデータをテーブルに挿入するときに再利用されます。MEMORY
テーブルでは、ハッシュテーブルで一般的に削除 + 挿入に関連付けられる問題も起こりません。MEMORY
テーブルは固定長の行ストレージフォーマットを使用します。VARCHAR
などの可変長型は、固定長を使用して格納されます。MEMORY
テーブルはBLOB
またはTEXT
カラムを含むことができません。MEMORY
はAUTO_INCREMENT
カラムのサポートを含みます。TEMPORARY
MEMORY
でないテーブルは、ほかのTEMPORARY
でないテーブルと同様に、すべてのクライアントで共有されます。
MEMORY
テーブルを作成するには、CREATE TABLE
ステートメントで ENGINE=MEMORY
句を指定します。
CREATE TABLE t (i INT) ENGINE = MEMORY;
エンジンの名前が表すように、MEMORY
テーブルはメモリーに格納されます。 デフォルトではハッシュインデックスを使用するため、単一値の検索には非常に高速であり、一時テーブルの作成には非常に役立ちます。 ただし、サーバーがシャットダウンすると、MEMORY
テーブルに格納されたすべての行が失われます。 定義は MySQL データディクショナリに格納されますが、サーバーの再起動時には空であるため、テーブル自体は引き続き存在します。
この例は、MEMORY
テーブルをどのように作成、使用、および削除できるかを示しています。
mysql> CREATE TABLE test ENGINE=MEMORY
SELECT ip,SUM(downloads) AS down
FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;
MEMORY
テーブルの最大サイズは max_heap_table_size
システム変数によって制限されます (デフォルト値は 16M バイト)。 MEMORY
テーブルに異なるサイズ制限を適用するには、この変数値を変更します。 CREATE TABLE
、それに続く ALTER TABLE
または TRUNCATE TABLE
の実質的な値は、テーブルの有効期限に使用される値です。 サーバーを再起動しても、既存の MEMORY
テーブルの最大サイズがグローバルの max_heap_table_size
値に設定されます。 各テーブルのサイズをこのセクションの後半で説明するように設定できます。
MEMORY
ストレージエンジンは HASH
と BTREE
の両方のインデックスをサポートしています。 ここに示すように USING
句を追加することによりどちらであるかを指定できます。
CREATE TABLE lookup
(id INT, INDEX USING HASH (id))
ENGINE = MEMORY;
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
B ツリーとハッシュインデックスの一般的な特徴については、セクション8.3.1「MySQL のインデックスの使用の仕組み」を参照してください。
MEMORY
テーブルでは、テーブル当たり最大で 64 個のインデックス、インデックス当たり 16 個のカラム、3072 バイトの最大キー長を持つことができます。
MEMORY
テーブルのハッシュインデックスでキーの重複の程度が高いと (同じ値を含むインデックスエントリが多い)、キー値に影響を与えるテーブルへの更新処理とすべての削除処理の速度が大きく低下します。 この低下の程度は重複の程度に比例します (または、インデックスカーディナリティーに反比例します)。 BTREE
インデックスを使用することで、この問題を回避できます。
MEMORY
テーブルには、非一意キーを持つことができます。 (これは、ハッシュインデックスの実装ではまれな特徴です。)
インデックスが付けられたカラムに NULL
値を含むことができます。
MEMORY
テーブルの内容はメモリーに格納されます。これは MEMORY
テーブルが、クエリーの処理中にその場でサーバーが作成する内部一時テーブルと共有する特性です。 ただし、2 つのタイプのテーブルには違いがあり、MEMORY
テーブルはストレージ変換の影響を受けませんが、内部一時テーブルは次のような影響があります。
内部一時テーブルが大きくなりすぎると、セクション8.4.4「MySQL での内部一時テーブルの使用」で説明したように、サーバーは自動的にオンディスクストレージに変換します。
ユーザー作成の
MEMORY
テーブルは、決してディスクテーブルに変換されません。
MySQL サーバーの起動時に MEMORY
テーブルに移入するには、init_file
システム変数を使用できます。 たとえば、INSERT INTO ... SELECT
や LOAD DATA
などのステートメントをファイルに挿入して永続データソースからテーブルをロードし、init_file
を使用してファイルに名前を付けることができます。 セクション5.1.8「サーバーシステム変数」およびセクション13.2.7「LOAD DATA ステートメント」を参照してください。
レプリケーションソースサーバーが停止して再起動すると、その MEMORY
テーブルは空になります。 この効果をレプリカにレプリケートするには、ソースが起動後に最初に特定の MEMORY
テーブルを使用するときに、そのテーブルの DELETE
ステートメントまたは (MySQL 8.0.22 から) TRUNCATE TABLE
ステートメントをバイナリログに書き込むことによってテーブルを空にする必要があることをレプリカに通知するイベントをログに記録します。 レプリカサーバーを停止して再起動すると、その MEMORY
テーブルも空になり、DELETE
または (MySQL 8.0.22 から) TRUNCATE TABLE
ステートメントが独自のバイナリログに書き込まれ、ダウンストリームレプリカに渡されます。
レプリケーショントポロジで MEMORY
テーブルを使用する場合、状況によっては、ソースのテーブルとレプリカのテーブルが異なることがあります。 失効した読取りまたはエラーを防ぐためのこれらの各状況の処理の詳細は、セクション17.5.1.21「レプリケーションと MEMORY テーブル」 を参照してください。
サーバーには、同時に使用されるすべての MEMORY
テーブルを保持するための十分なメモリーが必要です。
MEMORY
テーブルから各行を削除しても、メモリーは再利用されません。 テーブル全体が削除された場合にのみ、メモリーが再利用されます。 削除された行に以前に使用されたメモリーは同じテーブル内の新しい行に再利用されます。 MEMORY
テーブルの内容が必要でなくなったときに、それが使用していたすべてのメモリーを解放するには、DELETE
または TRUNCATE TABLE
を実行してすべての行を削除するか、DROP TABLE
を使用してテーブルを完全に削除します。 削除された行が使用していたメモリーを解放するには、ALTER TABLE ENGINE=MEMORY
を使用してテーブルを強制的に再作成します。
MEMORY
テーブルで 1 つの行に必要なメモリーは、次の式で計算されます。
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
ALIGN()
は行の長さを char
ポインタサイズのちょうど倍数にするための切り上げ係数を表します。sizeof(char*)
は 32 ビットマシンでは 4、64 ビットマシンでは 8 です。
前に述べたように、max_heap_table_size
システム変数は MEMORY
テーブルの最大サイズの制限値を設定します。 各テーブルの最大サイズを制御するには、各テーブルを作成する前に、この変数のセッション値を設定します。 (すべてのクライアントが作成した MEMORY
テーブルに、グローバル max_heap_table_size
値を使用するのでなければ、この値を変更しないでください。) 次は、2 つの MEMORY
テーブル (最大サイズがそれぞれ 1M バイトと 2M バイト) を作成する例です。
mysql> SET max_heap_table_size = 1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.01 sec)
mysql> SET max_heap_table_size = 1024*1024*2;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
両方のテーブルは、サーバーが再起動した場合、サーバーのグローバル max_heap_table_size
値に戻ります。
MEMORY
テーブルに対して CREATE TABLE
ステートメントの MAX_ROWS
テーブルオプションを指定して、テーブルに格納する予定の行数に関するヒントを提供することもできます。 これによって max_heap_table_size
値 (引き続き最大テーブルサイズの制約として機能) を超えてテーブルが拡大できなくなります。 MAX_ROWS
を使用できるだけの最大限の柔軟性を得るには、少なくとも各 MEMORY
テーブルが拡大できる値程度に max_heap_table_size
を設定してください。
MEMORY
ストレージエンジンに特化したフォーラムは、https://forums.mysql.com/list.php?92で参照できます。