MySQL MERGE存储引擎
2014-01-06 18:20:40 阿炯

本站赞助商链接,请多关照。 MERGE存储引擎,也即MRG_MyISAM引擎,是一个相同的可以被当作一个来用的MyISAM表的集合。“相同”意味着所有表同样的列和索引信息。不能合并列被以不同顺序列于其中的表,没有恰好同样列的表,或有不同顺序索引的表。而且任何或者所有的表可以用myisampack来压缩以节省存储空间和提高检索效率。

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

MERGE引擎类型允许把许多结构相同的表合并为一个表。然后可以执行查询,从多个表返回的结果就像从一个表返回的结果一样。每一个合并的表必须有同样的表定义。

MERGE存储引擎在下面这种使用场合会最为有用,如果需要把日志纪录不停的录入MySQL数据库,并且每天、每周或者每个月都创建一个单一的表,而且要制作来自多个表的合计查询,MERGE表这时会非常有效。然而这项功能有局限性,只能合并MyISAM表而且必须严格遵守相同的表定义的限制。虽然这看起来好像是一个大问题,但如果使用另外一种表类型(例如InnoDB),这种合并可能就不需要了。

可以对表的集合用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'),('freeoa'),('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 | freeoa |
| 3 | t2 |
+---+---------+

注意,也可以直接从MySQL之外直接操作.MRG文件:
shell> cd /mysql-data-directory/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表方面的问题
下列是已知关于MERGE表的问题:

如果使用ALTER TABLE 来把MERGE表变为其它表类型,到底层表的映射就被丢失了。取而代之的,来自底层MyISAM表的行被复制到已更换的表中,该表随后被指定新类型。

REPLACE不起作用。

没有WHERE子句,或者在任何被映射到一个打开的MERGE表上的任何一个表上的REPAIR TABLE,TRUNCATE TABLE, OPTIMIZE TABLE或ANALYZE TABLE,不能使用DROP TABLE, ALTER TABLE, DELETE FROM。如果这么做了,MERGE表将仍旧指向原始表,这样产生意外结果。解决这个不足的最简单办法是在执行任何一个这些操作之前发出一个FLUSH TABLES语句来确保没有MERGE表仍被保持打开。

一个MERGE表不能在整个表上维持UNIQUE约束。当执行一个INSERT, 数据进入第一个或者最后一个MyISAM表(取决于INSERT_METHOD选项的值,通常是最后一个定义的表)。MySQL确保唯一键值在那个MyISAM表里保持唯一,但不是跨集合里所有的表。

当创建一个MERGE表之时,没有检查去确保底层表的存在以及有相同的结构。当MERGE表被使用之时,MySQL检查每个被映射的表的记录长度是否相等,但这并不十分可靠。如果从不相似的MyISAM表创建一个MERGE表,非常有可能撞见奇怪的问题。

在MERGE表中的索引的顺序和它的底层表中的索引应该一样。如果使用ALTER TABLE给一个被用在MERGE表中的表添加一个UNIQUE索引,然后使用ALTER TABLE在MERGE表上添加一个非唯一索引,如果在底层表上已经有一个非唯一索引,对表的索引排序是不同的。(这是因为ALTER TABLE把UNIQUE索引放在非唯一索引之前以利于重复键的快速检测 )。因此对使用这样索引的表的查询可能返回不期望的结果。

在Windows下,在一个被MERGE表使用的表上DROP TABLE不起作用,因为MERGE引擎的表映射对MySQL的更上层隐藏。因为Windows不允许已打开文件的删除,首先必须刷新所有MERGE表(使用FLUSH TABLES)或在移除该表之前移除MERGE表。

所以它的相关特性可以总结如下:
1. 此表类似于SQL中的union机制。

2. 此表结构必须与基本表完全一致,包括列名、顺序。UNION表必须同属一个DATABASE。

3. 基本表类型必须是MyISAM。

4. 可以通过修改.mrg文件来修改MERGE表,每个基本表的名字占一行。注意:修改后要通过FLUSH TABLES刷新表缓存。

5. 对基本表的更改可以直接反映在此表上。

6. INSERT_METHOD的取值可以是: 0 不允许插入 FIRST 插入到UNION中的第一个表 LAST 插入到UNION中的最后一个表(4.0之后可用)。

7. 定义在它上面的约束没有任何作用,约束是由基本表控制的,例如两个基本表中存在着同样的一个Key值,那么在MERGE表中会有两个一样的Key值。

8. 连接的几张表都必须是myisam engine的。