單表 5000 萬行,需根據 col_a、col_b 兩欄組合判重,刪除重複保留一條。直接在原表操作會導致長事務、鎖升級、主從延遲,風險極高。
t1CREATE TABLE t1 (
id BIGINT PRIMARY KEY,
col_a VARCHAR(50),
col_b VARCHAR(50),
INDEX idx_ab (col_a, col_b)
) ENGINE=InnoDB;
INSERT INTO t1 (id, col_a, col_b)
SELECT id, col_a, col_b FROM big_table;
只抽取主鍵與判重欄位,體積縮減 90%+,建立聯合索引加速分組。
t2CREATE TABLE t2 LIKE t1;
INSERT INTO t2 (id, col_a, col_b)
SELECT id, col_a, col_b FROM t1
WHERE (col_a, col_b) IN (
SELECT col_a, col_b FROM t1
GROUP BY col_a, col_b
HAVING COUNT(*) > 1
)
AND id NOT IN (
SELECT MIN(id) FROM t1
GROUP BY col_a, col_b
HAVING COUNT(*) > 1
);
t2 存放所有待刪除的重複行主鍵(保留每組最小 id)。
-- 確認無誤後
DELETE bt FROM big_table bt
INNER JOIN t2 ON bt.id = t2.id;
分批提交(每 5000 行),配合 pt-archiver 或手寫迴圈,避免長鎖。
t2 留存完整刪除清單,支援審計與復原。NULL,需用 IFNULL(col, '') 統一處理,否則 GROUP BY 會將 NULL 視為獨立組。pt-heartbeat 監控,延遲超閾值暫停。