在 MySQL 資料庫中,刪除(DELETE)與更新(UPDATE)操作的開銷通常高於插入(INSERT)操作。因此,優秀的資料庫設計應盡量減少這類操作的頻率。本文將深入分析更新與刪除操作對性能的具體影響,並提供實戰優化策略。
資料庫執行更新操作時會引發一連串「連鎖反應」:
這些機制不僅降低了更新操作本身的效率,產生的磁碟碎片還會嚴重拖垮後續的查詢性能。針對此問題,主要有兩大應對策略:減少更新次數與避免更新。
以數據倉庫的「代碼清洗」場景為例:需關聯多張代碼表,將業務表的多個自編碼欄位批量更新。對比兩種寫法:
測試環境:2000 萬條測試數據。結果顯示,單語句更新耗時 2 分 59 秒,多語句更新耗時 29 分 48 秒,性能提升近 10 倍。
-- 單語句更新多欄位示例
UPDATE TBL_INCOME_TMP
SET
代碼1自編碼 = (SELECT SELFCODE FROM TBL_CODE1 WHERE ...),
代碼2自編碼 = (SELECT SELFCODE FROM TBL_CODE2 WHERE ...),
...
代碼n自編碼 = (SELECT SELFCODE FROM TBL_CODEn WHERE ...);
某考勤系統為提升查詢效率,在員工表中冗餘存儲「部門名稱」。原流程:先插入員工基礎信息,再關聯部門表更新部門名稱。因部門名稱為可變長字段,更新會產生碎片。
優化方案:插入員工表時,直接通過 JOIN 部門表將部門名稱一併寫入,完全省略 UPDATE 步驟。
INSERT INTO Employee_New (EmpID, EmpName, DeptName) SELECT E.EmpID, E.EmpName, D.DeptName FROM Employee_Source E JOIN Department D ON E.DeptID = D.DeptID;
許多開發者誤以為刪除操作輕量快速,實則不然:
應對策略同樣分為兩類:定期重組與避免刪除。
重組操作會重新排列表數據的物理順序,清除碎片中的空閒空間。當執行大量刪除/更新後,若統計信息更新無法改善性能,嘗試重組表數據往往能顯著提升存取速度。
場景:中間表 temp1 處理數據,將 flag=1 的數據轉移至正式表,並刪除中間表中這些記錄。若直接 DELETE,會留下海量碎片且空間不釋放。
優化方案:引入輔助臨時表 temp2
temp1 中需保留的數據(flag=0)插入 temp2;ALTER TABLE temp1 ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE 瞬間清空 temp1(不產生日誌,極快且釋放空間);temp2 數據插回 temp1。若保留數據僅佔 10%,此方案性能提升極其顯著。
參考《The Art of SQL》核心觀點:
總結:理解更新/刪除的底層代價,善用「合併操作」「以插代改」「以空代刪」等模式,配合合理的索引與表設計,才能構建高性能的 MySQL 應用。