如何在大型InnoDB表上提高DELETE FROM性能?

mpe*_*mpe 16 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;
Run Code Online (Sandbox Code Playgroud)

从表中删除大块的查询就像这样:

DELETE FROM problematic_table WHERE problematic_table.taxid = '57';
Run Code Online (Sandbox Code Playgroud)

像这样的查询花了将近一个小时才完成.我可以想象索引重写开销使得这些查询非常慢.

我正在开发一个将在预先存在的数据库上运行的应用程序.我很可能无法控制服务器变量,除非我强制要求对它们进行更改(我不愿意),所以我担心改变它们的建议没什么价值.

我已经尝试将INSERT ... SELECT那些我不想删除的行放到临时表中而只是删除其余的行,但是当to-delete与to-keep的比率转向to-keep时,这不再是一个有用的解决方案.

这是一张表,可能会在未来看到频繁的INSERTs和SELECTs,但没有UPDATEs.基本上,它是一个日志记录和参考表,需要不时删除部分内容.

我可以通过限制它们的长度来改善此表上的索引吗?切换到MyISAM帮助,DISABLE KEYS在交易期间支持吗?还有什么可以尝试提高DELETE性能?

编辑:一个这样的删除将是大约一百万行的顺序.

vdd*_*vdd 24

我有一个类似的场景,一个包含200万行的表和一个删除语句,它应该删除大约10万行 - 这需要大约10分钟才能完成.

检查配置后,我发现MySQL Server运行时默认值innodb_buffer_pool_size= 8 MB(!).

在以innodb_buffer_pool_size1.5GB 重启后,同样的情况需要10秒.

因此,如果"表的重新排序"可以适合于buffer_pool,则看起来存在依赖性.


小智 12

一旦完成,该解决方案可以提供更好的性能,但是该过程可能需要一些时间来实现.

BIT可以添加新列并默认TRUE为"活动"和FALSE"非活动".如果状态不够,则可以使用TINYINT256个可能的值.

添加这个新列可能需要很长时间,但一旦结束,只要您执行此操作PRIMARY就像删除一样,并且不对此新列编制索引,您的更新应该快得多.

InnoDB在如此DELETE庞大的表上花费这么长时间的原因是因为集群索引.它实际订单表格根据您的PRIMARY,第一UNIQUE它找到,或是别的什么东西可以作为判断足以取代,如果它不能找到PRIMARY或者UNIQUE,所以当一列被删除,现在身体重新排序整个表在磁盘上的速度和碎片整理.所以这不是DELETE那么长的事; 删除该行后的物理重新排序.

当您创建固定宽度列并更新而不是删除时,不需要在巨大的表中进行物理重新排序,因为行和表本身消耗的空间是不变的.

在非工作时间,DELETE可以使用单个删除不必要的行.此操作仍然很慢,但总体上比删除单个行快得多.

  • "将整个表物理地重新排序到磁盘上以进行速度和碎片整理" - 这是错误的.InnoDB行删除首先进入"更改缓冲区"; 这实际上延迟了删除工作.当删除发生时,从它所在的一个块中删除一行,然后考虑将该块与其邻居合并.没有大规模的重组. (5认同)