MERGE存储引擎
MERGE
存储引擎,也被称为MRG_MyISAM
发动机,是相同的集合MyISAM
可被用作一个表。“相同”表示所有表具有相同的列数据类型和索引信息。您不能合并MyISAM
以不同顺序列出列的表,在相应列中没有完全相同的数据类型或以不同顺序索引的表。但是,MyISAM
可以使用myisampack压缩任何或所有表。请参见“myisampack-生成压缩的只读MyISAM表”。诸如此类的表之间的差异无关紧要:
- 相应列和索引的名称可以不同。
- 表,列和索引的注释可以不同。
- 表的选项,如
AVG_ROW_LENGTH
,MAX_ROWS
或PACK_KEYS
可以不同。
MERGE
表的替代方法是分区表,该表将单个表的分区存储在单独的文件中,并使某些操作可以更有效地执行。有关更多信息,请参见分区。
创建MERGE
表时,MySQL .MRG
在磁盘上创建一个文件,该文件包含MyISAM
应该用作一个表的基础表的名称。表的表格式MERGE
存储在MySQL数据字典中。基础表不必与MERGE
表位于同一数据库中。
您可以使用SELECT
,DELETE
,UPDATE
,和INSERT
上MERGE
表。您必须在映射到表的表上具有SELECT
,DELETE
和UPDATE
特权。MyISAM
MERGE
注意使用
MERGE
表会带来以下安全问题:如果用户有权访问MyISAM
表t
,则该用户可以创建一个访问的MERGE
表。但是,如果用户的权限在随后撤销,用户可以继续访问通过这样做。m
t
t
t
m
DROP TABLE
与MERGE
表一起使用仅会丢弃MERGE
规范。基础表不受影响。
要创建MERGE
表,必须指定一个选项以指示要使用的表。您可以选择指定一个选项来控制向表中插入的方式。使用或的值分别导致在第一个或最后一个基础表中进行插入。如果您未指定任何选项,或者您指定的值为,则不允许在表中插入,并且尝试这样做会导致错误。UNION=(list-of-tables)
MyISAM
INSERT_METHOD
MERGE
FIRST
LAST
INSERT_METHOD
NO
MERGE
以下示例显示如何创建MERGE
表:
mysql>CREATE TABLE t1 ( -> a INT NOT NULLAUTO_INCREMENT PRIMARY KEY , -> message CHAR(20))ENGINE =MyISAM; mysql>CREATE TABLE t2 ( -> a INT NOT NULLAUTO_INCREMENT PRIMARY KEY , -> message CHAR(20))ENGINE =MyISAM; 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 NULLAUTO_INCREMENT , -> message CHAR(20),INDEX (a)) ->ENGINE =MERGE UNION =(t1,t2)INSERT_METHOD =LAST ;
列在基础表中a
索引为a ,但在表中未索引。在那里对其进行了索引,但没有将其作为索引,因为表无法在基础表的集合上强制唯一性。(类似地,在基础表中具有索引的列应在表中建立索引,但不能作为索引。)PRIMARY KEY
MyISAM
MERGE
PRIMARY KEY
MERGE
UNIQUE
MERGE
UNIQUE
创建MERGE
表之后,可以使用它发出对整个表组进行操作的查询:
mysql>SELECT *FROM total; +--- +--------- + | a | message | +--- +--------- + | 1 | Testing | | 2 | table | | 3 | t1 | | 1 | Testing | | 2 | table | | 3 | t2 | +--- +--------- +
要将MERGE
表重新映射到其他MyISAM
表集合,可以使用以下方法之一:
DROP
该MERGE
表并重新创建它。使用来改变底层表的列表。
ALTER TABLE tbl_name UNION=(...)
也可以使用
ALTER TABLE ... UNION=()
(即带有空UNION
子句)删除所有基础表。但是,在这种情况下,该表实际上是空的,并且插入失败,因为没有基础表可以使用新行。这样的表作为用创建新MERGE
表的模板可能有用CREATE TABLE ... LIKE
。
基础表定义和索引必须紧密符合表的定义MERGE
。在MERGE
打开作为表一部分的表时(而不是在MERGE
创建表时)检查一致性。如果任何表未通过一致性检查,则触发打开表的操作将失败。这意味着在访问表MERGE
时对a 中表的定义进行更改可能会导致失败MERGE
。应用于每个表的一致性检查是:
- 基础表和
MERGE
表必须具有相同的列数。 - 基础表和
MERGE
表中的列顺序必须匹配。 此外,将对父
MERGE
表和基础表中每个对应列的规范进行比较,并且必须满足以下检查条件:- 基础表和
MERGE
表中的列类型必须相等。 - 基础表和
MERGE
表中的列长度必须相等。 - 基础表和
MERGE
表的列可以是NULL
。
- 基础表和
基础表必须至少具有与
MERGE
表一样多的索引。基础表可能比该MERGE
表具有更多索引,但不能更少。注意
存在一个已知的问题,即在
MERGE
表和基础MyISAM
表中,同一列上的索引必须具有相同的顺序。参见错误#33653。每个索引必须满足以下检查条件:
- 基础表和
MERGE
表的索引类型必须相同。 - 基础表和
MERGE
表的索引定义中的索引部分(即,复合索引中的多个列)的数目必须相同。 对于每个索引部分:
- 索引部件的长度必须相等。
- 索引零件类型必须相等。
- 索引零件语言必须相等。
- 检查分度是否可以
NULL
。
- 基础表和
如果MERGE
由于基础表存在问题而无法打开或使用表,则CHECK TABLE
显示有关引起问题的表的信息。
MERGE表的优缺点
MERGE
表可以帮助您解决以下问题:
- 轻松管理一组日志表。例如,您可以将不同月份的数据放入单独的表中,使用myisampack压缩其中的一些数据,然后创建一个
MERGE
表以将它们用作一个表。 - 获得更高的速度。您可以根据某些条件拆分一个大型只读表,然后将各个表放在不同的磁盘上。以
MERGE
这种方式构造的表可能比使用单个大表要快得多。 - 执行更有效的搜索。如果您确切知道要查找的内容,则可以仅在基础表之一中搜索某些查询,而
MERGE
在其他表中使用该表。您甚至可以拥有许多MERGE
使用重叠表集的不同表。 - 执行更有效的维修。修复映射到
MERGE
表的单个较小的表比修复单个大表要容易。 - 立即将多个表映射为一个。一个
MERGE
表不需要维护自己的索引,因为它使用了各个表的索引。因此,MERGE
表集合的创建或重新映射速度非常快。(MERGE
即使没有创建索引,在创建表时仍必须指定索引定义。) - 如果您有一组表,可以根据需要从中创建一个大表,则可以根据需要从中创建一个
MERGE
表。这快得多,并节省了大量磁盘空间。 - 超出操作系统的文件大小限制。每个
MyISAM
表都有此限制,但MyISAM
表的集合则不受此限制。 - 您可以
MyISAM
通过定义MERGE
映射到单个表的表来为表创建别名或同义词。这样做不会对性能造成任何明显的影响(memcpy()
每次读取仅两次间接调用和调用)。
MERGE
表的缺点是:
MyISAM
一个MERGE
表只能使用相同的表。- 某些
MyISAM
功能在MERGE
表格中不可用。例如,您不能FULLTEXT
在MERGE
表上创建索引。(您可以FULLTEXT
在基础MyISAM
表上创建索引,但是不能MERGE
使用全文本搜索来搜索表。) - 如果
MERGE
表是非临时表,则所有基础MyISAM
表都必须是非临时表。如果MERGE
表是临时表,则MyISAM
表可以是临时表和非临时表的任意组合。 MERGE
表使用的文件描述符比MyISAM
表更多。如果10个客户端使用的MERGE
表映射到10个表,则服务器使用(10×10)+ 10个文件描述符。(10个客户端中的每个客户端都有10个数据文件描述符,客户端之间共享10个索引文件描述符。)- 索引读取速度较慢。当您读取索引时,
MERGE
存储引擎需要对所有基础表发出读取,以检查哪个表最匹配给定索引值。为了读取下一个索引值,MERGE
存储引擎需要搜索读取的缓冲区以找到下一个值。仅当一个索引缓冲区用完时,存储引擎才需要读取下一个索引块。这会使MERGE
索引在eq_ref
搜索时慢很多,但在搜索时却不会慢很多ref
。有关详细信息eq_ref
,并ref
请参见第13.8.2,“EXPLAIN语句”。
合并表问题
以下是MERGE
表的已知问题:
在5.1.23之前的MySQL Server版本中,可以使用非临时子MyISAM表创建临时合并表。
从5.1.23版开始,MERGE子级通过父表被锁定。如果父母是临时的,则它不会被锁定,因此孩子也不会被锁定。MyISAM表的并行使用损坏了它们。
- 如果用于
ALTER TABLE
将MERGE
表更改为另一个存储引擎,则到基础表的映射将丢失。取而代之的是,将基础MyISAM
表中的行复制到更改后的表中,该表随后使用指定的存储引擎。 - 在
INSERT_METHOD
一个表选择MERGE
表指示哪个底层MyISAM
使用表插入到MERGE
表中。但是,对该AUTO_INCREMENT
表使用 table选项对MyISAM
插入表无效,MERGE
直到至少有一行直接插入到表中为止MyISAM
。 - 一个
MERGE
表不能在整个表上维护唯一性约束。当执行时INSERT
,数据进入第一个或最后一个MyISAM
表(由INSERT_METHOD
选项确定)。MySQL确保唯一键值在该MyISAM
表中保持唯一,但在整个集合的所有基础表中均不唯一。 由于
MERGE
引擎无法对基础表集实施唯一性,因此REPLACE
无法按预期工作。两个关键事实是:REPLACE
只能在要写入的基础表中检测唯一键冲突(由INSERT_METHOD
选项决定)。这与MERGE
表本身中的冲突不同。- 如果
REPLACE
检测到唯一键冲突,它将仅更改其要写入的基础表中的相应行;即由INSERT_METHOD
选项确定的第一个或最后一个表。
类似的考虑也适用
INSERT ... ON DUPLICATE KEY UPDATE
。MERGE
表不支持分区。也就是说,您不能对MERGE
表进行分区,也不能对MERGE
表的任何基础MyISAM
表进行分区。你不应该使用
ANALYZE TABLE
,REPAIR TABLE
,OPTIMIZE TABLE
,ALTER TABLE
,DROP TABLE
,DELETE
没有一个WHERE
条款,或TRUNCATE TABLE
任何被映射到一个开放的表的MERGE
表。如果这样做,该MERGE
表仍可能引用原始表,并且会产生意外的结果。要变通解决此问题,MERGE
通过FLUSH TABLES
执行任何命名的操作之前发出一条语句,确保没有表保持打开状态。意外的结果包括对
MERGE
表的操作将报告表损坏的可能性。如果这在基础MyISAM
表上的命名操作之一之后发生,则损坏消息是虚假的。为了解决这个问题,请FLUSH TABLES
在修改MyISAM
表后发出一条语句。DROP TABLE
在表上使用的MERGE
表在Windows上不起作用,因为MERGE
存储引擎的表映射是从MySQL的上层隐藏的。Windows不允许删除打开的文件,因此您必须先删除所有MERGE
表(使用FLUSH TABLES
)或删除MERGE
表,然后再删除表。- 访问表时(例如,作为or 语句的一部分)检查
MyISAM
表的定义和MERGE
表。这些检查通过比较列顺序,类型,大小和关联的索引来确保表的定义与父表的定义匹配。如果表之间存在差异,则返回错误,并且语句失败。因为这些检查是在打开表时进行的,所以对单个表的定义的任何更改(包括列更改,列顺序和引擎更改)都将导致语句失败。SELECT
INSERT
MERGE
- 该
MERGE
表及其基础表中索引的顺序应相同。如果用于ALTER TABLE
向UNIQUE
表中使用的MERGE
表添加索引,然后用于在表ALTER TABLE
上添加非MERGE
唯一索引,则在基础表中已经存在非唯一索引的情况下,表的索引顺序会有所不同。(发生这种情况是因为ALTER TABLE
将UNIQUE
索引放在非唯一索引之前,以便于快速检测重复键。)因此,对具有此类索引的表的查询可能会返回意外结果。 - 如果遇到类似于错误1017(HY000)
tbl_name
的错误消息:找不到文件:'. MRG'(errno:2),则通常表明某些基础表未使用MyISAM
存储引擎。确认所有这些表都是MyISAM
。 - 表中的最大行数
MERGE
为2 64(〜1.844E + 19;与MyISAM
表相同)。无法将多个MyISAM
表合并为一个MERGE
具有多于此行数的表。 - 当前已知将
MyISAM
不同行格式的基础表与父MERGE
表一起使用会失败。请参阅错误#32364。 有效时,您无法更改非临时
MERGE
表的联合列表LOCK TABLES
。以下就不能正常工作:CREATE TABLE m1 ...ENGINE =MRG_MYISAM ...;LOCK TABLES t1WRITE , t2WRITE , m1WRITE ;ALTER TABLE m1 ...UNION =(t1,t2) ...;但是,您可以使用临时
MERGE
表来执行此操作。您不能
MERGE
使用CREATE ... SELECT
,临时MERGE
表和非临时表创建MERGE
表。例如:CREATE TABLE m1 ...ENGINE =MRG_MYISAM ...SELECT ...;尝试执行此操作会导致错误:
tbl_name
不是BASE TABLE
。- 在某些情况下,如果基础表包含或列,则基础表和基础表
PACK_KEYS
之间的表选项值不同MERGE
会导致意外结果。解决方法是,用于确保所有涉及的表都具有相同的值。错误35646)CHAR
BINARY
ALTER TABLE
PACK_KEYS