我有一个相当大的 InnoDB 表,其中包含大约 1000 万行(并且不断增加,预计会变成该大小的 20 倍)。每行不是那么大(平均为 131 B),但有时我不得不删除其中的一大块,这需要很长时间。这是表结构:
CREATE TABLE `problematic_table` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`taxid` int(10) unsigned NOT NULL,
`blastdb_path` varchar(255) NOT NULL,
`query` char(32) NOT NULL,
`target` int(10) unsigned NOT NULL,
`score` double NOT NULL,
`evalue` varchar(100) NOT NULL,
`log_evalue` double NOT NULL DEFAULT '-999',
`start` int(10) unsigned DEFAULT NULL,
`end` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `taxid` (`taxid`),
KEY `query` (`query`),
KEY `target` (`target`),
KEY `log_evalue` (`log_evalue`)
) ENGINE=InnoDB AUTO_INCREMENT=7888676 DEFAULT CHARSET=latin1;
从表中删除大块的查询就像这样:
DELETE FROM problematic_table WHERE problematic_table.taxid = '57';
这样的查询只用了将近一个小时就完成了。我可以想象索引重写开销使这些查询非常慢。
我正在开发一个将在预先存在的数据库上运行的应用程序。我很可能无法控制服务器变量,除非我强制更改它们(我不希望这样做),所以我担心更改这些的建议没有什么值(value)。
我尝试将那些我不想删除的行 INSERT ... SELECT
删除到临时表中,然后删除其余的行,但作为删除与删除的比率-keep 转向 to-keep,这不再是一个有用的解决方案。
这是一张将来可能会频繁看到 INSERT
和 SELECT
但没有 UPDATE
的表。基本上,它是一个需要不时删除部分内容的日志记录和引用表。
我可以通过限制索引的长度来改进此表上的索引吗?在交易期间切换到支持 DISABLE KEYS
的 MyISAM 会有所帮助吗?我还能尝试什么来提高 DELETE
性能?
编辑:这样的删除之一是大约一百万行。
最佳答案
我有一个类似的场景,一个有 200 万行的表和一个删除语句,它应该删除大约 10 万行 - 这样做大约需要 10 分钟。
检查配置后,我发现 MySQL Server 以默认 innodb_buffer_pool_size
= 8 MB (!) 运行。
在 innodb_buffer_pool_size
= 1.5GB 重启后,同样的场景需要 10 秒。
所以看起来“重新排序表”是否适合 buffer_pool 似乎存在依赖关系。
关于mysql - 如何提高大型 InnoDB 表的 DELETE FROM 性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14284238/