Mysql

如何提高 InnoDB DELETE 性能?

  • August 7, 2017

所以我有這個審計表(跟踪我數據庫中任何表的操作):

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

我需要開始歸檔過時的項目。該表已增長到大約 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)
)

我讓它在我的伺服器上執行了 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 |

因此,我認為 400 萬行不應該需要 3 天才能刪除。我將 innodb_buffer_pool_size 設置為 3GB,並且伺服器未設置為使用 one_file_per_table。還有哪些其他方法可以提高 InnoDB 刪除性能?(在 Mac OSX 上執行 MySQL 5.1.43)

您可以批量刪除數據。

在 SQL Server 中,語法是delete top X表中的行。然後,您在一個循環中執行此操作,每個批次都有一個事務(當然,如果您有多個語句),因此要保持事務簡短並僅在短時間內保持鎖定。

在 MySQL 語法中:DELETE FROM userTable LIMIT 1000

對此有一些限制(例如,不能LIMIT在帶有連接的刪除中使用),但在這種情況下,您可能可以這樣做。

當涉及到複製時,使用LIMITwith還有一個額外的危險;DELETE刪除的行有時在從屬設備上的刪除順序與在主設備​​上的刪除順序不同。

引用自:https://dba.stackexchange.com/questions/1497