すでに分かっている
MERGE
テーブルの問題点は次のようなものです。
MERGE
テーブルを別のストレージエンジンに変えるために、ALTER
TABLE
テーブルを利用すると、基礎テーブルへのマッピングが失われます。その代わりに、基礎
MyISAM
テーブルのレコードが変化したテーブルにコピーされ、そしてそれは指定されたストレージエンジンを利用します。
MERGE
エンジンは、基礎となるテーブル全体に一意性を持たせられないため、REPLACE
が想定したとおりに機能しません。主な現象は次の
2 つです。
REPLACE
は、書き込み先の基礎テーブル
(INSERT_METHOD
によって決まる)
でしかユニークキー違反を検出できません。これは
MERGE
テーブルそのものにおける違反とは異なります。
REPLACE
がそのような違反を検出した場合、同じユニークキーの値を持つ行がすべての基礎テーブルに存在する可能性があるにも関わらず、対応する行が含まれる最初の基礎テーブルの該当行しか変更されません。
INSERT
... ON DUPLICATE KEY UPDATE
についても同様の問題に考慮する必要があります。
MERGE
テーブルは分割をサポートしません。これは、MERGE
テーブルも、MERGE
テーブルの基礎
MyISAM
テーブルも分割ができないことを意味します。
開いている MERGE
テーブルにマップされているテーブルに対して、REPAIR
TABLE
、OPTIMIZE
TABLE
、DROP
TABLE
、ALTER
TABLE
、WHERE
節のない
DELETE
、TRUNCATE
TABLE
、または
ANALYZE TABLE
を使用しないようにしてください。それをすると
MERGE
テーブルは元のテーブルを参照することがあるので、予期しない結果をもたらす可能性があります。このような事態を防ぐために一番簡単な方法は、FLUSH
TABLES
ステートメントを事前に発行することによって、すべての
MERGE
テーブルを閉じておくことです。
予期しない結果として、MERGE
テーブルに対する操作によってテーブルの破壊が報告される可能性があります。ただし、前の段落に示したような基礎
MyISAM
テーブルに対する操作
(REPAIR
TABLE
、OPTIMIZE
TABLE
など)
のあとで表示される破壊メッセージは誤りです。これに対処するには、MyISAM
テーブルを変更したあとで
FLUSH
TABLES
ステートメントを発行します。
MERGE
ストレージエンジンのテーブルマッピングは
MySQL
の上位レイヤーから隠れているので、MERGE
テーブルによって使用されている
DROP TABLE
は Windows
では機能しません。Windows
では開いているファイルを削除することはできないので、まず
MERGE
テーブルをフラッシュするか
(FLUSH
TABLES
を使う)、テーブルをドロップする前に
MERGE
テーブルをドロップする必要があります。
MERGE
テーブルは、そのテーブル全体に対して一意性制約を保持することができません。INSERT
を行うとき、データは最初、または最後の
MyISAM
テーブルに入ります。INSERT_METHOD
オプションの値による)。MySQL
は MyISAM
テーブルの中では一意の値はそのまま残ることを保障しますが、すべてのテーブルのコレクションの中ではそうではありません。
MERGE
テーブルの
INSERT_METHOD
テーブルオプションは、MERGE
テーブルへの挿入に使用する基礎
MyISAM
テーブルを指定します。ただし、その
MyISAM
テーブルに
AUTO_INCREMENT
テーブルオプションを使用しても、1
つ以上の行が MyISAM
テーブルに直接挿入されるまで、MERGE
テーブルへの挿入には効果がありません。
MySQL 5.1.15
以降のバージョンでは、アクセスされたときに
MyISAM
テーブルと
MERGE
テーブルの定義が確認されます。(例
SELECT
か
INSERT
ステートメントの一部として)。そのように確認することによって、テーブル定義と親
MERGE
テーブル定義がカラムの順番、タイプ、サイズ、そして関連するインデックスなどに関して一致することを保障します。テーブル間で違いがあれば、エラーが発生し、ステートメントは失敗します。
テーブルが開かれるときにこのような確認が行われるので、カラムの変更、カラムの順序付け、エンジンの入れ替えなど、単一テーブルの定義の変更によってステートメントが失敗します。
MySQL 5.1.14 とそれ以前のバージョンにて
MERGE
テーブルを修正、または作成するとき、基礎テーブルが
MyISAM
テーブル内に存在し、それらが同一の構造であることを保証するための確認は行われません。MERGE
テーブルが使用されるとき、MySQL
はすべてのマップされたテーブルの行の長さが等しいかどうかを確認しますが、これは絶対間違いのないものではありません。異なる
MyISAM
テーブルから
MERGE
テーブルを作成すると、未知の問題に直面する可能性が高いです。
同じように、MyISAM
テーブル以外から
MERGE
テーブルを作成したり、または基礎テーブルを
MyISAM
テーブル以外にドロップしたり変更したりすると、あとで
MERGE
テーブルを使用するときまでエラーは発生しません。
基礎 MyISAM
テーブルは、MERGE
テーブルが作成されるときには存在する必要がないので、すべての基礎テーブルが配置されるまで
MERGE
テーブルを使用しなければ、テーブルをどんな順番で作成しても構いません。また、MERGE
テーブルが与えられた時間内に使用されないことを保障できるのであれば、基礎テーブルのバックアップ、復元、変更、ドロップ、または再作成などのメンテナンスを行うことができます。基礎テーブルに対して作業を行っている間に、それらを除外するために
MERGE
テーブルを一時的に再定義する必要はありません。
MERGE
テーブル内と、その基礎テーブルのインデックスの順番は同一でなければいけません。ALTER
TABLE
を使用して、MERGE
テーブル内で使用されるテーブルに
UNIQUE
インデックスを追加し、次に
ALTER TABLE
を使用して MERGE
テーブル上に一意でないインデックスを追加した場合、基礎テーブル内に一意でないインデックスがすでに存在していると、それらのテーブルのインデックス順序は異なります。(この問題が発生するのは、重複キーをすばやく検出できるように
ALTER TABLE
が一意でないインデックスの前に
UNIQUE
インデックスを配置するためです。)その結果、そのようなインデックスを持つテーブルに対するクエリーは予想外の結果をもたらします。
次のようなエラーメッセージが表示された場合:
「ERROR 1017 (HY000): Can't find file:
'mm
.MRG' (errno: 2)」
通常、基礎テーブルの中に
MyISAM
ストレージエンジンを使用していないものがあることを示します。これらのテーブルがすべて
MyISAM
であることを確認してください。
サーバーが
--with-big-tables
オプションを使用して構築されたのであれば、MERGE
テーブルの最大行数は 264
(~1.844E+19、MyISAM
テーブルと同様) です。(標準 MySQL 5.1
の標準バイナリはすべてこのオプションで構築されます。詳細は、項2.10.2. 「典型的な configure
オプション」を参照してください。)複数の
MyISAM
テーブルを、この数よりも多くの行を含む単一の
MERGE
テーブルにマージすることはできません。
MERGE
ストレージエンジンは、INSERT
DELAYED
ステートメントをサポートしません。
親の MERGE
テーブルを持つ
MyISAM
テーブル内で異なる基礎の行フォーマットを使用すると、現時点では失敗することが確認されています。Bug#32364 を参照してください。
MySQL 5.1.20
までのバージョンでは、基礎テーブルの問題により
MERGE
テーブルを開いたり使用したりできない場合、CHECK
TABLE
を実行すると問題の原因となっているテーブルの情報が表示されます。
MySQL 5.1.23 以降のバージョンでは、LOCK TABLES
が有効になっているときは、一時的でない
MERGE
テーブルの結合リストを変更できません。次の処理は機能しません。
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ...; LOCK TABLES t1 WRITE, t2 WRITE, m1 WRITE; ALTER TABLE m1 ... UNION=(t1,t2) ...;
ただし、一時的な
MERGE
テーブルではこの処理を実行できます。
MySQL 5.1.23
以降のバージョンでは、CREATE
... SELECT
で
MERGE
テーブル
(一時的な MERGE
テーブルと一時的でない
MERGE
テーブルのどちらも)
を作成することはできません。次に例を示します。
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ... SELECT ...;
「table is not BASE
TABLE
」というエラーメッセージが表示されます。