将大表从MyISAM转换到Innodb

我有一个大约300M行的MyISAM格式的表格,我想转换成Innodb

我最初的目标是通过改变表格模式来减less使用,使索引更简单。 我倾倒了所有的桌子,放弃了它,用较less的索引来重新创build它,现在我正在重新导入。 但是,我忘了指定它应该是innodb而不是myisam。

我可以只做标准的ALTER TABLE … ENGINE = INNODB吗? 有这样一个巨大的桌子,我应该知道有什么特别的东西吗?

数据导入操作需要大约12个小时 – 我不喜欢这样做。 因此,我为什么要把它转换。

以下exerpt出自“ 高性能MySQL,第二版 ”一书。

这是一本很好的书,我会把它推荐给任何人。

简短的回答是:

随着你的桌子的大小和条件,不pipe你select什么方法,我想你都有可能在漫长的等待中。


表转换

将表从一个存储引擎转换为另一个存储引擎有几种方法,每种方法都有其优点和缺点。

改变表

mysql> ALTER TABLE mytable ENGINE = Falcon; 

这种语法适用于所有的存储引擎,但有一个问题:它可能需要很长时间。 MySQL会将旧表的一行一行地复制到一个新表中。 在此期间,您可能会使用所有服务器的磁盘I / O容量,并且原始表将在转换运行时被读locking。

转储和导入

为了获得对转换过程的更多控制权,您可以select首先使用mysqldump实用程序将表转储到文本文件。 一旦你转储了表,你可以简单地编辑转储文件来调整它所包含的CREATE TABLE语句。 请确保更改表名及其types,因为即使它们具有不同的types,也不能在同一数据库中具有相同名称的两个表,并且mysqldump默认在CREATE TABLE之前写入DROP TABLE命令,所以如果你不小心,你可能会丢失你的数据!

CREATE和SELECT

第三种转换技术是第一种机制的速度和第二种机制的安全性之间的折中。 不要一次性转储整个表或将其全部转换,而要创build新表并使用MySQL的INSERT … SELECT语法来填充它,如下所示:

 mysql> CREATE TABLE innodb_table LIKE myisam_table; mysql> ALTER TABLE innodb_table ENGINE=InnoDB; mysql> INSERT INTO innodb_table SELECT * FROM myisam_table; 

如果你没有太多的数据,那么效果很好,但是如果你这样做的话,那么递增填充表往往更有效率,在每个块之间提交事务,所以撤消日志不会变大。 假设id是主键,请重复运行此查询(每次使用更大的x和y值),直到将所有数据复制到新表中:

 mysql> START TRANSACTION; mysql> INSERT INTO innodb_table SELECT * FROM myisam_table -> WHERE id BETWEEN x AND y; mysql> COMMIT; 

这样做之后,您将剩下原来的表格,当您完成这个工作时,您可以放下原来的表格,以及现在已完全填充的新表格。 如果需要,请小心locking原始表格,以防止获得不一致的数据副本!

ALTER TABLE语句本质上是做同样的事情:服务器创build一个临时表,它复制所有的行,然后做一个RENAME。 InnoDB和MyISAM在磁盘上的格式是非常不同的,所以我不希望你find任何捷径。

另一种说法(你可能知道,但它会帮助其他人阅读):InnoDB的磁盘格式高度依赖于主键,因为它基于它聚集logging。 因此,在处理大型InnoDB表时,在select主键之前要三思,因为改变它会重build整个表,就像手头的问题一样。

无论如何,我build议先在中等大小的桌子上做一些testing,然后再测量一下。