将大表从MyISAM转换为Innodb


9

我有一个表,该表包含约3亿行MyISAM格式,我想转换为Innodb

我最初的目标是通过将表架构更改为具有更简单的索引来减少使用量。我转储了所有表,将其删除,用更少的索引重新创建了表,现在重新导入。但是,我忘记指定它应该是innodb而不是myisam。

我可以只做标准的ALTER TABLE ... ENGINE = INNODB吗?如此庞大的桌子,我应该注意什么特别的地方?

数据导入操作大约需要12个小时-我不愿意再次这样做。因此,为什么我只想转换它。


有了300M行,无论如何,MyISAM可能更快,更好地适合这种大小的表!
马克·亨德森

Answers:


14

以下摘录来自《高性能MySQL,第二版》一书。

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

简短的答案是:

根据您的表大小和条件,无论选择哪种方法,我都认为您可能需要等待很长时间。


表转换

有几种方法可以将表从一个存储引擎转换为另一个存储引擎,每种方法各有利弊。

更改表

mysql> ALTER TABLE mytable ENGINE = Falcon;

该语法适用于所有存储引擎,但有一个陷阱:它可能需要很多时间。MySQL将执行旧表到新表的逐行复制。在此期间,您可能会使用服务器的所有磁盘I / O容量,并且原始表将在转换运行时被读取锁定。

转储和导入

为了更好地控制转换过程,您可以选择首先使用mysqldump实用程序将表转储到文本文件中。转储表后,您只需编辑转储文件即可调整其中包含的CREATE TABLE语句。确保更改表名及其类型,因为即使两个表具有不同的类型,也不能在同一个数据库中拥有两个名称相同的表,并且mysqldump默认在CREATE TABLE之前写入DROP TABLE命令。 ,如果不注意,可能会丢失数据!

创建和选择

第三种转换技术是第一种机制的速度与第二种机制的安全性之间的折衷。创建新表并使用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;

完成此操作后,您将剩下原始表(使用完后可以将其删除)和新表(现已完全填充)。如有必要,请小心锁定原始表,以防止获取不一致的数据副本!


2

ALTER TABLE语句实质上执行相同的操作:服务器创建一个临时表,在其中复制所有行,然后执行RENAME。InnoDB和MyISAM之间的磁盘格式极为不同,因此我不希望您找到任何捷径。

另一个注意事项(您可能已经知道,但这会帮助其他人阅读):InnoDB的磁盘格式高度依赖于主键,因为它基于主键对记录进行聚类。因此,当使用大型InnoDB表时,在选择主键之前请三思,因为更改主键会重建整个表,就像手头的问题一样。

无论如何,我建议先在中等大小的表上进行一些测试,然后安排时间。


2
MySQL中的任何表更改操作(包括添加索引)都会重建表。
David Pashley 09年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.