首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

億級 InnoDB 表去重實戰:5000 萬記錄兩欄判重最佳方案

     編輯:MySQL 綜合教學

問題背景

單表 5000 萬行,需根據 col_a、col_b 兩欄組合判重,刪除重複保留一條。直接在原表操作會導致長事務、鎖升級、主從延遲,風險極高。

標準三步走方案

步驟 1:建立輕量臨時表 t1

CREATE 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%+,建立聯合索引加速分組。

步驟 2:識別重複,寫入二臨時表 t2

CREATE 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)。

步驟 3:業務決策後,關聯原表批量刪除

-- 確認無誤後
DELETE bt FROM big_table bt
INNER JOIN t2 ON bt.id = t2.id;

分批提交(每 5000 行),配合 pt-archiver 或手寫迴圈,避免長鎖。

核心優勢

  • 零業務停機:原表持續可讀寫。
  • 可驗證可回滾:t2 留存完整刪除清單,支援審計與復原。
  • 索引友善:臨時表小、索引精準,分組去重秒級完成。

避坑提醒

  • 若判重欄位含 NULL,需用 IFNULL(col, '') 統一處理,否則 GROUP BY 會將 NULL 視為獨立組。
  • 磁碟空間預留:臨時表 + Binlog 可能佔用原表 30%-50% 空間。
  • 主從延遲監控:刪除階段啟用 pt-heartbeat 監控,延遲超閾值暫停。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved