重複資料刪除技術優勢:釋放空間、提升備份效率、加速恢復、利於容災。
DELETE FROM table_a a
WHERE (col1, col2) IN (
SELECT col1, col2 FROM table_a
GROUP BY col1, col2 HAVING COUNT(*) > 1
);
子查詢每次執行掃描全表,大表極易拖垮資料庫。
-- 1. 建立暫存表保存重複鍵值
CREATE TABLE temp_dup_keys AS
SELECT col1, col2 FROM table_a
GROUP BY col1, col2 HAVING COUNT(*) > 1;
-- 2. 依暫存表刪除 (避免重複掃描)
DELETE FROM table_a a
WHERE (a.col1, a.col2) IN (SELECT col1, col2 FROM temp_dup_keys);
-- 3. 清理
DROP TABLE temp_dup_keys;
Oracle 隱藏欄位 ROWID 編碼資料物理位置,越新寫入的 ROWID 通常越大 (同一物件)。
DELETE FROM table_a a
WHERE a.ROWID != (
SELECT MAX(b.ROWID) FROM table_a b
WHERE a.col1 = b.col1 AND a.col2 = b.col2
);
-- 1. 建立暫存表:每組重複鍵保留最大 ROWID
CREATE TABLE temp_keep AS
SELECT col1, col2, MAX(ROWID) AS keep_rid
FROM table_a
GROUP BY col1, col2;
-- 2. 刪除非保留行
DELETE FROM table_a a
WHERE a.ROWID != (
SELECT b.keep_rid FROM temp_keep b
WHERE a.col1 = b.col1 AND a.col2 = b.col2
);
-- 3. 提交並清理
COMMIT;
DROP TABLE temp_keep;
-- 1. 去重存入暫存表
CREATE TABLE temp_distinct AS SELECT DISTINCT * FROM table_a;
-- 2. 清空原表 (TRUNCATE 比 DELETE 快且不產生 UNDO)
TRUNCATE TABLE table_a;
-- 3. 寫回去重資料
INSERT INTO table_a SELECT * FROM temp_distinct;
-- 4. 清理
DROP TABLE temp_distinct;
或單指令 (適合中小表):
INSERT INTO table_bak SELECT DISTINCT * FROM table_a;
TRUNCATE TABLE table_a;
INSERT INTO table_a SELECT * FROM table_bak;
DROP TABLE table_bak;
| 方法 | 適用規模 | 特點 |
|---|---|---|
| 單句 IN 子查詢 | 小表 < 10 萬列 | 簡單但重複掃描 |
| 暫存表中介 | **中大型表** | **掃描一次、多次利用,效能最佳** |
| ROWID 保留最新 | 需保留最新業務邏輯 | 利用物理屬性無需額外時間戳欄位 |
| DISTINCT + TRUNCATE | 完全重複列 | 最徹底、速度最快 |
ALTER TABLE ... TRUNCATE PARTITION 並行處理。ANALYZE TABLE ... COMPUTE STATISTICS 或 DBMS_STATS 更新統計。