Mysql

我應該停止一個效率極低的 MySQL DELETE 語句嗎?

  • July 8, 2015

我在來自 Linode 的 1GB 1CPU SSD 虛擬機中的 MySQL 5.5 上執行以下語句:

DELETE table
FROM (
   SELECT MAX(id) id, field
   FROM table
   GROUP BY field
) temp_table
INNER JOIN table
   ON table.field = temp_table.field
WHERE table.id != temp_table.id

它已經卡在Sending data狀態超過 24 小時,現在我知道為什麼了:它有一個糟糕的執行計劃:

mysql> EXPLAIN SELECT 1 FROM (SELECT MAX(id) id, field FROM table GROUP BY field) temp_table INNER JOIN table ON table.field = temp_table.field WHERE table.id != temp_table.id
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows   | Extra                           |
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL | 381888 |                                 |
|  1 | PRIMARY     | users      | ALL  | NULL          | NULL | NULL    | NULL | 984873 | Using where; Using join buffer  |
|  2 | DERIVED     | users      | ALL  | NULL          | NULL | NULL    | NULL | 984873 | Using temporary; Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+--------+---------------------------------+
3 rows in set (46.12 sec)

(MySQL 5.5 不允許EXPLAIN DELETE,所以我EXPLAIN SELECT 1按照這個答案來做)

請注意,只有它EXPLAIN本身需要 46 秒才能完成。

我應該停止這種說法並嘗試將事情做得更好,還是應該等待?

我看到查詢在做什麼。您正在嘗試刪除大量行並為每個欄位保留最後插入的 id。

我有一個更好的方法。

DROP TABLE IF EXISTS keys_to_keep;
CREATE TABLE keys_to_keep
(
   id INT NOT NULL,
   PRIMARY KEY (id)
);
INSERT INTO keys_to_keep SELECT MAX(id) FROM mytable GROUP BY field;
CREATE TABLE mytable_new LIKE mytable;
INSERT INTO mytable_new
SELECT B.* FROM keys_to_keep A INNER JOIN mytable B USING (id);
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;

檢查我的表。如果它只有最後一次出現的欄位,那麼您可以

DROP TABLE keys_to_keep;
DROP TABLE mytable_old;

試一試 !!!

我以前推薦過這種技術

我還討論了將軟刪除作為替代方案(需要維護一個附加的 ID 標記為已刪除的映射表或一個額外的列來標記已刪除的行):

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