mysql - 如何提高大型 InnoDB 表的 DELETE FROM 性能?

标签 mysql performance innodb

我有一个相当大的 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,这不再是一个有用的解决方案。

这是一张将来可能会频繁看到 INSERTSELECT 但没有 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/

相关文章:

php - Laravel Eloquent Eager Loading 和 ownToMany 太慢

mysql - 从派生表优化 SQL 查询

mysql - 如何在删除表后回收 InnoDB 中的磁盘空间

MySQL:列数据是否在更新/删除时从硬盘驱动器中安全删除?

mysql - 使用 R 更新多个 mysql 行

php - 数组中的年份作为键,然后填充当年的许多日期

php - 使用地理定位查找最近的城市

java - 为什么 Java 比其他解释型语言有更好的性能?

performance - 如何在家做软件性能测试

mysql - MyISAM 和触发器原子性