我有一个 MyISAM 表,目前包含大约 5400 万条记录,大小为 20 GB。设计这个数据库时做出了错误的选择。我不是数据库专家,但由于这个表经常被写入而很少被查询,所以 InnoDB 似乎是更好的选择。问题是这个表必须几乎总是可以写入。其中一个字段是带时间戳的字段。记录可以追溯到 5 年前——我只需要保留最近 6 个月的记录。我尝试了一些删除操作,删除 200,000 行大约需要 20 分钟,在此期间表被锁定并且无法写入。有人能建议我如何减少这个表的大小而不会将其锁定几个小时吗?有没有更快的方法来删除不需要的行?我从未将 MyISAM 表转换为 InnoDB 表。这是一个漫长的过程吗?
答案1
我终于有时间重新审视这个项目,为了完整起见,我想发布我最终做了什么。我认为,DELETE FROM 花费这么长时间的原始问题与我如何指定要删除的行有关。我使用了类似于
DELETE FROM table WHERE starttime < 20150101 limit 200000;
starttime 字段实际上是 DATETIME。我最终使用以下代码创建了一个新表
CREATE TABLE new_table LIKE existing_table;
然后改变新表的引擎
ALTER TABLE new_table ENGINE=InnoDB;
然后重命名
RENAME TABLE existing_table TO old_table, new_table TO existing_table;
之后我需要将旧表中 6 个月的数据导入到新表中
INSERT INTO existing_table SELECT * FROM old_table WHERE starttime BETWEEN DATE_SUB(NOW(), INTERVAL 6 MONTH) AND NOW();
感谢 Martin 的建议。我是 serverfault 的新手,因此我不确定如何将他的评论标记为答案。
答案2
MyISAM 仅适用于 SELECT。Innodb 具有单独的 READ 和 WRITE 队列。因此,当您删除 200,000 行时,表不会被锁定。表锁定是 MyISAM 在生产中的一大限制。对于大多数用途,InnoDB 比 MyISAM 慢,但由于锁定机制更好,在某些情况下可以执行得更快;MyISAM 在执行插入/更新时锁定整个表以进行读取。InnoDB 可以进行行级锁定,从而允许在表上进行多个并发写入和读取
http://kakadba.blogspot.in/2014/02/innodb-vs-myisam.html
将 MyISAM 转换为 INNODB
你可以逐表进行
ALTER TABLE table_name ENGINE=InnoDB;
或者您可以尝试使用脚本一次性完成所有操作
https://stackoverflow.com/questions/3856435/how-to-convert-all-tables-from-myisam-into-innodb