第15章:存储引擎和表类型 / 15.3. MERGE存储引擎

15.3.1. MERGE表 方面的问题

MERGE存储引擎,也被认识为MRG_MyISAM引擎,是一个相同的可以被当作一个来用的MyISAM表的集合。“相同”意味着所有表同样的 列和索引信息。你不能合并列被以不同顺序列于其中的表,没有恰好同样列的表,或有不同顺序索引的表。而且,任何或者所有的表可以用myisampack来压缩。请参阅8.2节,“myisampack — 生成压缩的只读MyISAM表”。表选项的差异,比如AVG_ROW_LENGTH, MAX_ROWS或PACK_KEYS都不重要。

当你创建一个MERGE表之时,MySQL在磁盘上创建两个文件。文件名以表的名字开始,并且有一个扩展名来指明文件类型。一个.frm文件存储表定义,一个.MRG文件包含被当作一个来用的表的名字。这些表作为MERGE表自身,不必要在同一个数据库中。

你可以对表的集合用SELECT, DELETE, UPDATE和INSERT。你必须对你映射到一个MERGE表的这些表有SELECT, UPDATE和DELETE 的权限。

如果你DROP MERGE表,你仅在移除MERGE规格。底层表没有受影响。

当你创建一个MERGE表之时,你必须指定一个UNION=(list-of-tables)子句,它说明你要把哪些表当作一个来用。如果你想要对MERGE表的插入发生在UNION列表中的第一个或最后一个表上,你可以选择地指定一个INSERT_METHOD选项。使用FIRST或LAST值使得插入被相应地做在第一或最后一个表上。如果你没有指定INSERT_METHOD选项,或你用一个NO值指定该选项。往MERGE表插入记录的试图导致错误。

下面例子说明如何创建一个MERGE表:

mysql> CREATE TABLE t1 (
    ->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->    message CHAR(20));
mysql> CREATE TABLE t2 (
    ->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->    message CHAR(20));
mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql> CREATE TABLE total (
    ->    a INT NOT NULL AUTO_INCREMENT,
    ->    message CHAR(20), INDEX(a))
    ->    TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;

注意,一个列在MERGEN表中被索引,但没有被宣告为一个PRIMARY KEY,因为它是在更重要的MyISAM表中。这是必要的,因为MERGE表在更重要的表中的设置上强制非唯一性。

创建MERGE表之后,你可以发出把一组表当作一体来操作的查询:

mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

注意,你也可以直接从MySQL之外直接操作.MRG文件:

shell> cd /mysql-data-directory/current-database
shell> ls -1 t1 t2 > total.MRG
shell> mysqladmin flush-tables

要重映射一个MERGE表到一个不同的MyISAM表集,你可以执行下列之一:

·         DROP MERGE表并且重建它。

·         使用ALTER TABLE tbl_name UNION=(...)来改变底层表的列表。

·         改变.MRG文件,并对MERGE表或者所有底层表发出一个FLUSH TABLE语句来强制存储引擎去读新的定义文件。

MERGE表可以帮你解决以下问题:

·         容易地管理一套日志表。比如,你可以把不同月的数据放进分离的表中,用myisampack压缩其中的一些,并随后创建一个MERGE表来把它们当作一个来使用。

·         获得更快的速度。你可以以一些标准来分割大的只读表,然后放进不同磁盘上的单个表中。基于此的一个MERGE表可比使用大表要快得多。

·         执行更有效的搜索。如果你确切知道要搜索什么,对一些查询你可以只在被分割的表的其中之一来搜索,并且对其它使用MERGE。你甚至有许多不同的MERGE表,它们使用有重叠的表套。

·         执行更有效的修补。修补被映射到一个MERGE表中的单个表比修补单个大型表要更轻松。

·         即刻映射许多表成一个。MERGE表不需要维护它自己的索引,因为它使用大哥表的所用。因此,MERGE表集合是非常块地创建或重映射。(注意,当你创建一个MERGE表之时,即使没有索引被创建,你必须仍然指定索引定义)。

·         如果根据需要或按照批次,你有一组要合起来作为一个大表的表,你应该根据需要对它们创建一个MERGE表来替代大表。这样要快得多而且节约大量的磁盘空间。

·         超过操作系统的文件尺寸限制。每个MyISAM表都受制于这个限制,但是一个MyISAM表的集合则不然。

·         你可以通过定义一个映射到单个表的MERGE表来为一个MyISAM表创建一个别名或“同物异名”。这样做应该没有真实的可察觉的性能影响 (对每个读只有一些间接调用和memcpy()调用)。

MERGE表的缺点:

·         你可以对MERGE表使用仅相同的MyISAM表。

·         你不能在MERGE表中使用很多MyISAM功能。比如,你不能在MERGE表上创建FULLTEXT索引。(当然,你可以在底层MERGE 表上创建FULLTEXT索引,但是你不能用全文搜索来搜索MERGE表)。

·         如果MERGE表是非临时的,所有底层MyISAM表也必须是永久的。如果MERGE表是临时的,MyISAM表可以是任何临时&非临时的混合。

·         MERGE表使用更多的文件描述符。如果是个客户端正使用一个映射到10个表的MERGE表,服务器使用(10*10)+10个文件描述符。(10个数据文件描述符给10个客户端每人一个,并且在客户端之间共享10个索引文件描述符)。

· 键读会更慢。当你读一个键的时候,MERGE存储引擎需要在所有 底层表上发出一个读以检查哪一个接近匹配给定的键。如果你随后做了一个read-next,MERGE存储引擎需要搜索读缓冲来找出下一个键。只有当一个键缓冲被耗尽,存储引擎才需要读下一个 键块。这使得MERGE键在eq_ref搜索中非常慢,但在ref搜索中不是太慢。请参阅7.2.1节,“EXPLAIN 语法(获取SELECT相关信息)” 以获得更多关于eq_ref和ref的信息。