如何提高 InnoDB DELETE 性能?

Der*_*ney 9 mysql innodb performance delete

所以我有这个审计表(跟踪我数据库中任何表的操作):

CREATE TABLE `track_table` (
  `id` int(16) unsigned NOT NULL,
  `userID` smallint(16) unsigned NOT NULL,
  `tableName` varchar(255) NOT NULL DEFAULT '',
  `tupleID` int(16) unsigned NOT NULL,
  `date_insert` datetime NOT NULL,
  `action` char(12) NOT NULL DEFAULT '',
  `className` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `userID` (`userID`),
  KEY `tableID` (`tableName`,`tupleID`,`date_insert`),
  KEY `actionDate` (`action`,`date_insert`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)

我需要开始归档过时的项目。该表已增长到大约 5000 万行,因此我可以删除行的最快方法是一次删除一个表(基于tableName)。

这工作得很好,但在一些写入繁重的表上,它不会完成。我的查询删除所有delete对 tupleID/tableName 组合具有关联操作的项目:

DELETE FROM track_table WHERE tableName='someTable' AND tupleID IN (
  SELECT DISTINCT tupleID FROM track_table
  WHERE tableName='someTable' AND action='DELETE' AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
)
Run Code Online (Sandbox Code Playgroud)

我让它在我的服务器上运行了 3 天,但它从未在最大的表上完成。解释输出(如果我将删除切换到选择:

| id | select_type        | table       | type | possible_keys      | key     | key_len | ref        | rows    | Extra                        |
|  1 | PRIMARY            | track_table | ref  | tableID            | tableID | 257     | const      | 3941832 | Using where                  |
|  2 | DEPENDENT SUBQUERY | track_table | ref  | tableID,actionDate | tableID | 261     | const,func |       1 | Using where; Using temporary |
Run Code Online (Sandbox Code Playgroud)

所以 400 万行不应该需要 3 天才能删除,我想。我将 innodb_buffer_pool_size 设置为 3GB,并且服务器未设置为使用 one_file_per_table。我可以通过哪些其他方式提高 InnoDB 删除性能?(在 Mac OSX 上运行 MySQL 5.1.43)

Mar*_*ian 11

可以批量删除数据。

在 SQL Server 中,语法是delete top X表中的行。然后你在循环中进行,每个批次都有一个事务(当然,如果你有多个语句),所以要保持事务简短并只在短时间内保持锁定。

在 MySQL 语法中: DELETE FROM userTable LIMIT 1000

对此有一些限制(LIMIT例如,不能在带有连接的删除中使用),但在这种情况下,您可以这样做。

在复制方面使用LIMITwith还有一个额外的危险DELETE;有时删除的行在从站上删除的顺序与在主站上删除的顺序不同。


Rol*_*DBA 6

尝试使用临时表方法。尝试这样的事情:

第1步) CREATE TABLE track_table_new LIKE track_table;

第2步) INSERT INTO track_table_new SELECT * FROM track_table WHERE action='DELETE' AND date_insert >= DATE_SUB(CURDATE(), INTERVAL 30 day);

步骤 3) ALTER TABLE track_table RENAME track_table_old;

第四步) ALTER TABLE track_table_new RENAME track_table;

步骤 5) DROP TABLE track_table_old;

我没有在步骤 2 中包含 tuple 字段。请看看这是否会产生预期的效果。如果这是您想要的,您可能希望完全放弃 tuple 字段,除非您出于其他原因使用 tuple 字段。