Oracle 10g 單表 5000 萬條數據,需刪除 3000 萬歷史記錄。表上有「創建日期」索引和「Sequence ID」索引。直接執行 DELETE 會導致:
DECLARE
v_deleted NUMBER := 0;
BEGIN
LOOP
DELETE FROM large_table
WHERE create_date < DATE '2023-01-01' -- 利用日期索引
AND ROWNUM <= 10000; -- 每次提交 1 萬行
v_deleted := v_deleted + SQL%ROWCOUNT;
COMMIT; -- 釋放 Undo,避免 ORA-01555
EXIT WHEN SQL%ROWCOUNT = 0;
DBMS_LOCK.SLEEP(0.1); -- 降低系統負載
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total deleted: ' || v_deleted);
END;
/
關鍵點:
ROWNUM 限制單次事務規模。COMMIT 防止 Undo 爆滿。SLEEP 讓出 CPU/I/O 資源。-- 1. 創建新表只保留需要的數據
CREATE TABLE large_table_keep AS
SELECT * FROM large_table
WHERE create_date >= DATE '2023-01-01';
-- 2. 重建索引、約束、授權
-- 3. 交換表名
RENAME large_table TO large_table_old;
RENAME large_table_keep TO large_table;
-- 4. 刪除舊表釋放空間
DROP TABLE large_table_old PURGE;
優勢:幾乎不產生 Redo/Undo,速度快數量級;注意:需停機維護窗口,處理外鍵依賴。
若表按日期範圍分區:
ALTER TABLE large_table DROP PARTITION p_2022_12 UPDATE GLOBAL INDEXES;
秒級完成,零業務影響,自動維護全局索引。
WHERE seq_id < :max_id 分批刪除。ALTER INDEX idx_name UNUSABLE; 刪除後 REBUILD。ALTER TABLE large_table ENABLE ROW MOVEMENT; ALTER TABLE large_table SHRINK SPACE;ALTER INDEX idx_name REBUILD ONLINE;EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'LARGE_TABLE');5000 萬表刪 3000 萬,**分批循環刪除** 是無停機首選;有維護窗口則 **新表保留法** 最快;長期規劃請採用 **分區表**。切記:小事務、勤提交、利用索引、事後縮容。