MERGE テーブルは、MySQL バージョン 3.23.25 で新たに導入されました。コードはまだガンマ版ですが、比較的安定しているはずです。
MERGE テーブル(MRG_MyISAM テーブルとも呼ばれます)は、1 つのテーブルとして使用できる同一の MyISAM テーブルの集合です。テーブルの集合には、SELECT、DELETE、UPDATE のみを実行できます。MERGE テーブルに対して DROP を実行すると、MERGE の仕様のみが破棄されます。
WHERE なしで DELETE FROM merge_table を使用すると、テーブルに対するマッピングのみが消去され、マップされたテーブルの内容は削除されないことに注意してください(これは 4.1 で修正する予定です)。
同一のテーブルとは、すべてのテーブルが同一のカラムおよびキー情報で作成されていることを意味します。カラムのパック方法が異なるテーブル、保持するカラムがまったく同じでないテーブル、あるいはキーの順序が異なるテーブルはマージできません。ただし、一部のテーブルは myisampack で圧縮できます。 See 項4.8.4. 「myisampack(MySQL 圧縮読み取り専用テーブルジェネレータ)」。
MERGE テーブルを作成すると、.frm テーブル定義ファイルおよび .MRG テーブルリストファイルが作成されます。.MRG には、1 つのインデックスファイルとして使用される複数のインデックスファイル(.MYI ファイル)のリストのみが含まれています。4.1.1 より前のバージョンでは、使用されるすべてのテーブルを MERGE テーブルと同じデータベースに配置する必要がありました。
今のところ、MERGE テーブルにマップするテーブルに対しては、SELECT、UPDATE、DELETE の各特権が必要です。
MERGE テーブルには、次のような効果があります。
一連のログテーブルを簡単に管理できる。たとえば、各月のデータを別々のファイルに収録し、それらの一部を myisampack で圧縮した後に、MERGE を作成してそれらを 1 つのファイルとして使用することができる。
処理速度が速くなる。大きな読み取り専用テーブルをいくつかの基準に基づいて分割し、分割した各部分を別々のディスクに配置できる。この場合、MERGE テーブルを作成すれば、大きなテーブルを使用する場合に比べてはるかに処理が速くなる(RAID を使用した場合も同じ効果が得られる)。
より効率的に検索できる。処理の対象を正確に把握していれば、一部のクエリに対して分割されたテーブルの 1 つで検索を行い、その他のクエリに対して MERGE を使用することができる。多数のさまざまな MERGE テーブルをアクティブにすることもできる。この場合、ファイルが重複していてもかまわない。
より効率的に修復できる。1 つの大きなファイルを修復するより、MERGE ファイルにマップされたファイルを個別に修復する方が簡単である。
多数のファイルを 1 つのファイルとして即座にマップできる。MERGE テーブルは、個々のテーブルのインデックスを使用する。MERGE テーブル独自のインデックスを保持する必要はない。このため、MERGE テーブルの集合の作成または再マップにはほとんど時間がかからない。MERGE テーブルを作成するときは、キー定義を指定する必要があることに注意する。
一連のテーブルをオンデマンドまたはバッチで大きなテーブルに結合する場合は、代わりにそれらのテーブルに対してオンデマンドで MERGE テーブルを作成した方がよい。この方が時間がかからず、ディスク領域も大幅に節約できる。
オペレーティングシステムのファイルサイズ制限を回避できる。
1 つのテーブル上で MERGE を使用するだけで、テーブルのエイリアス/シノニムを作成できる。これによってパフォーマンスが特に影響を受けることはない(読み取りのたびに数回の間接的な呼び出しと memcpy() の呼び出しが発生するのみ)。
MERGE テーブルの欠点は次のとおりです。
MERGE テーブルには同一の MyISAM テーブルしか使用できない。
REPLACE を使用できない。
MERGE テーブルはより多くのファイル記述子を使用する。10 個のテーブルをマップする MERGE テーブルを 10 人のユーザが使用している場合は、10 10 + 10 個のファイル記述子を使用することになる(10 人のユーザに 10 個ずつのデータファイルと、10 個の共有インデックスファイル)。
キーの読み取りが遅い。キーに対して読み取りを行うと、MERGE ストレージエンジンは構成要素であるべてのテーブルに対して読み取りを発行して、指定されたキーに最も一致するテーブルをチェックする。その後に "read-next" を実行すると、MERGE ストレージエンジンは読み取りバッファを検索して次のキーを検出する。1 つのキーバッファがすべて使われるまでストレージエンジンは次のキーブロックを読み取らない。このため、eq_ref 検索では MERGE キーの処理にかなり時間がかかるが、ref 検索ではそれほど時間がかからない。 See 項5.2.1. 「EXPLAIN 構文(SELECT に関する情報の取得)」。
"開いている" MERGE テーブルによってマップされているテーブルには、DROP TABLE、ALTER TABLE、WHERE 節なしの DELETE FROM table_name、REPAIR TABLE、TRUNCATE TABLE、OPTIMIZE TABLE、または ANALYZE TABLE を実行できない。これを実行すると、MERGE テーブルが元のテーブルを参照するおそれがあり、予期しない結果を得ることがある。この問題を最も簡単に回避するには、FLUSH TABLES コマンドを発行して "開いている" MERGE テーブルを残さないようにする。
MERGE テーブルを作成するときに、1 つにまとめたいテーブルを UNION=(list-of-tables) で指定する必要があります。オプションとして、MERGE テーブルへの挿入が UNION リスト内の最初のテーブルと最後のテーブルのどちらで行われるかを、INSERT_METHOD で指定できます。INSERT_METHOD を指定しなかった場合、または NO を指定した場合は、MERGE テーブルに対するすべての INSERT コマンドでエラーが返されます。
次の例は、MERGE テーブルの使い方を示しています。
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
CREATE TABLE total (a INT NOT NULL AUTO_INCREMENT, message CHAR(20), KEY(a))
TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
SELECT * FROM total;
total テーブルではキーが一意にならないため、このテーブルでは UNIQUE または PRIMARY KEY を作成していないことに注意してください。
MySQL サーバの外部から直接 .MRG ファイルを操作することもできます。
shell> cd /mysql-data-directory/current-database shell> ls -1 t1.MYI t2.MYI > total.MRG shell> mysqladmin flush-tables
これで次のような操作を実行できるようになります。
mysql> SELECT * FROM total; +---+---------+ | a | message | +---+---------+ | 1 | Testing | | 2 | table | | 3 | t1 | | 1 | Testing | | 2 | table | | 3 | t2 | +---+---------+
注意: a カラムは、PRIMARY KEY として宣言されていますが、実際には一意ではないことに注意してください。MERGE テーブルでは、これを構成する一連の MyISAM テーブル全体にわたる一意性を確保できないからです。
MERGE テーブルをマップし直すには、次のいずれかの操作を実行します。
テーブルに対して DROP を実行し、テーブルを再作成する。
ALTER TABLE table_name UNION=(...) を使用する。
.MRG ファイルを変更し、MERGE テーブルとこれを構成するすべてのテーブルに対して FLUSH TABLE を発行することで、ストレージエンジンが新しい定義ファイルを読み取るようにする。