刪除表數據的兩大核心命令 DELETE 與 TRUNCATE,雖同為「清空數據」,但在事務語義、高水位標記 (HWM)、空間回收、觸發器、權限模型、並發行為上存在本質差異。本文從內核機制出發,給出決策矩陣。
| 維度 | DELETE | TRUNCATE |
|---|---|---|
| 語句類型 | DML | DDL(隱式提交) |
| 事務控制 | 可 ROLLBACK | 不可回滾(隱式 COMMIT 前後各一次) |
| 高水位標記 (HWM) | 不變 | 重置至段起始位置 |
| 空間回收 | 不回收(極值仍佔用) | 立即釋放 Extent(含索引) |
| 執行速度 | 慢(逐行生成 Undo/Redo) | 極快(僅更新數據字典、HWM) |
| 觸發器 | 觸發 ROW/STATEMENT 級 DELETE 觸發器 | 不觸發任何觸發器 |
| WHERE 條件 | 支持任意條件過濾 | 不支持(全表清空) |
| 權限授予 | GRANT DELETE ON table TO user | 無法單獨授予 TRUNCATE 權限(需 DROP ANY TABLE 或 DBA) |
| 父表限制 | 受外鍵約束,需先刪子表或禁用約束 | 不可直接 TRUNCATE 被引用的父表(需先 DISABLE FK) |
| 索引狀態 | 索引保留 VALID | 全局索引變 UNUSABLE(12c+ 可 UPDATE INDEXES 維護) |
| 閃回恢復 | FLASHBACK TABLE ... TO BEFORE DROP 不適用 | FLASHBACK TABLE ... TO BEFORE DROP 秒級恢復(Recyclebin) |
ORA-01555 snapshot too old 並膨脹 Undo 表空間。FULL TABLE SCAN 仍需掃描 HWM 以下所有塊,性能不升反降。SEG$.HWM = 0、SEG$.BLOCKS = INITIAL、釋放 Extent Map。UNUSABLE,需 ALTER INDEX ... REBUILD。TRUNCATE TABLE t UPDATE GLOBAL INDEXES 同步維護索引,業務零中斷。FLASHBACK TABLE t TO BEFORE DROP 瞬時恢復元數據,無需還原備份。IF 需保留部分數據 (WHERE 條件) → DELETE
ELSE IF 表被外鍵引用且無法 DISABLE FK → DELETE (分批提交)
ELSE IF 需觸發審計/同步觸發器 → DELETE
ELSE IF 權限模型禁止 DROP/TRUNCATE → DELETE
ELSE IF 表極大(>100GB)且維護窗口極短 → TRUNCATE (配合 UPDATE GLOBAL INDEXES)
ELSE IF 需快速釋放空間給其他段使用 → TRUNCATE
ELSE IF 需保留「誤刪可閃回」安全網 → TRUNCATE (啟用 Recyclebin)
ELSE → TRUNCATE (首選)
NEXTVAL;若業務依賴主鍵從 1 開始,需手動 ALTER SEQUENCE ... RESTART。ORA-02266。方案:ALTER TABLE child DISABLE CONSTRAINT fk_xxx; TRUNCATE parent; ALTER TABLE child ENABLE CONSTRAINT fk_xxx;(注意 ENABLE 會驗證數據)。UPDATE GLOBAL INDEXES。DELETE FROM big_table; → ~45 分鐘,產生 200GB Undo/Redo,HWM 不變。TRUNCATE TABLE big_table UPDATE GLOBAL INDEXES; → ~3 秒,Redo < 10MB,空間即時釋放。結論:TRUNCATE 是「重置表狀態」的核武器,DELETE 是「精準切除」的手術刀。生產環境建立「清表操作審批單」,強制記錄業務場景、表大小、索引狀態、回滾需求,由 DBA 簽署後執行,杜絕誤用 TRUNCATE 導致業務中斷或索引失效。