單次 DELETE 數百萬列會導致:長時間鎖定表、UNDO 表空間暴增、Redo Log 暴增、可能觸發 Snapshot Too Old 錯誤。
CREATE OR REPLACE PROCEDURE delete_in_batches(
p_table_name IN VARCHAR2,
p_condition IN VARCHAR2,
p_batch_size IN NUMBER DEFAULT 10000
) AS
v_deleted NUMBER := 0;
v_sql VARCHAR2(4000);
BEGIN
v_sql := 'DELETE FROM ' || p_table_name ||
' WHERE ' || p_condition ||
' AND ROWNUM <= :batch_size';
LOOP
EXECUTE IMMEDIATE v_sql USING p_batch_size;
v_deleted := v_deleted + SQL%ROWCOUNT;
EXIT WHEN SQL%ROWCOUNT = 0;
COMMIT; -- 每批提交,釋放鎖與 UNDO
END LOOP;
COMMIT;
DBMS_OUTPUT.PUT_LINE('完成:共刪除 ' || v_deleted || ' 筆資料');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
/
SET TIMING ON
EXEC delete_in_batches('HS_DLF_DOWNLOG_HISTORY', 'NUMDLFLOGGUID < 11100000', 10000);
PRAGMA AUTONOMOUS_TRANSACTION;| 方法 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| Partition Drop/Truncate | 表已分區,需刪除整個歷史分區 | 秒級完成,不產生 UNDO/Redo | 需預先規劃分區 |
| CTAS (Create Table As Select) | 保留資料佔比小(<20%) | 速度快,可重建索引 | 需鎖表、重建權限/約束/索引 |
| DBMS_REDEFINITION | 線上重組,零停機 | 不影響線上存取 | 設定複雜,需額外空間 |