生產環境中一張千萬筆資料的表格因匯入失誤導致全表重複,且系統不可停機、不可全量刪除重建,必須在線快速清除重複列。
假設表 TBL,主鍵為 (COL1, COL2) 並已建立索引。
CREATE TABLE tbl_tmp AS SELECT DISTINCT * FROM tbl;
TRUNCATE TABLE tbl;
INSERT INTO tbl SELECT * FROM tbl_tmp;
缺點:全表掃描、建表、截斷、再插入,產生大量 REDO/UNDO,耗時極長,生產環境不可接受。
DELETE FROM tbl
WHERE rowid IN (
SELECT a.rowid
FROM tbl a, tbl b
WHERE a.rowid > b.rowid
AND a.col1 = b.col1
AND a.col2 = b.col2);
原理:ROWID 全資料庫唯一,保留較小的 ROWID。限制:若重複筆數超過 2 筆(N>2),需多次執行或改用方案三。
-- 保留最大 ROWID
DELETE FROM tbl a
WHERE rowid NOT IN (
SELECT MAX(b.rowid)
FROM tbl b
WHERE a.col1 = b.col1
AND a.col2 = b.col2);
-- 或使用關聯子查詢
DELETE FROM tbl a
WHERE rowid < (
SELECT MAX(b.rowid)
FROM tbl b
WHERE a.col1 = b.col1
AND a.col2 = b.col2);
優點:單次掃描即可處理任意 N 重複,配合主鍵索引效能極佳。
DELETE FROM tbl
WHERE rowid NOT IN (
SELECT MAX(rowid)
FROM tbl
GROUP BY col1, col2);
或結合 HAVING COUNT(*) > 1 只針對有重複的群組操作,減少不必要的索引查找。
SELECT COUNT(*) FROM tbl GROUP BY col1, col2 HAVING COUNT(*) > 1 確認重複分布。WHERE ROWNUM <= 10000 循環),避免長交易阻塞。ANALYZE TABLE tbl COMPUTE STATISTICS 更新統計資訊。大表去重核心原則:避免全表建表、利用 ROWID 定位、配合索引單次掃描。方案三/四為生產環境首選。