2013-12-15 48 views
2

Iv'e只是從同事聽說,一個關係數據庫刪除行是非常危險的(關於索引和級聯動作)關係數據庫 - 刪除還是不刪除?

他說,允許刪除一個解決方案是有一個「過時」字段爲每個實體而是將該字段設置爲true以將該行標記爲「已刪除」。

當然,這需要您在所有的查詢來獲取所有的「專用」 ==假(這是相當麻煩的)

我的問題是:

  1. 他是正確的?如果是的話 - 究竟刪除究竟有什麼危險?
  2. 他的解決方案是一個很好的做法嗎?
  3. 此解決方案的任何替代方法都可用?

謝謝。

+0

http://stackoverflow.com/a/820489/477878 –

回答

2

如果您的架構結構合理,並且在需要時使用事務,刪除操作非常安全,並且使用刪除操作,您的性能將遠遠優於您的朋友所建議的方法。

插入一個新元素可能會變得棘手,因爲要刪除一個元素。我想知道你的朋友建議如何解決這個問題。

CRUD操作在這裏已經有很長時間了,關係數據庫的創建者在優化它們方面做得很好。任何試圖用這種黑客來勝過幾十年的逐步改進的嘗試很可能會失敗。

應用您的朋友建議的解決方案可能會導致擁有龐大的數據庫,只有一小部分未刪除的元素。這樣你的查詢也會變得更慢。

現在說了所有我想支持一點點的另一邊。有些情況下,您的朋友建議的解決方案可能是唯一的選擇。每當某些查詢變慢時,您無法更改模式。另外,正如其他人在他們的答案中所建議的,如果您使用「標記爲已刪除」的方法,刪除的數據將可以恢復(在其他答案中可能會再次提及,也可能不會再好)。

+0

不一定意見不一,但爲什麼它會提供更好的性能來刪除? MySQL中缺少過濾索引? –

+1

我擁有在大型表格中大量減緩批次刪除的第一手經驗。 –

+0

你確定它不是造成這種緩慢的數據庫結構? –

1

危險?服務器或數據中心會爆炸嗎?

我認爲你的同事沉迷於一些誇張。

如果你不想要,你不需要級聯更新或刪除,但它比手動清理更容易。這是您在創建模式時所做的選擇。

將行標記爲使用標記進行刪除是另一種方式,但這只是另一種選擇。您必須更努力地查找所有不良行並運行批處理作業以將其刪除。

如果您有保留要求,對模式進行分區並將較舊的記錄移入倉庫進行歷史分析和報告更爲典型。在這種情況下,您不會刪除任何內容,只需在一段時間後將其移出即可。

1
  1. 是的,他是對的。數據庫(特別是索引)針對插入和刪除進行了優化,可能會非常緩慢。即使將索引字段設置爲空也會導致相同的問題。我看到級聯是一個較小的問題,因爲數據庫不應該被配置爲自動執行危險的級聯。

  2. 是的,將記錄標記爲「不活動」,「刪除」,「不推薦」(您的選擇)是解決刪除相關性能問題的標準和首選實踐。

    不過,晉級以上,它只適用於事務(相對於檔案)表,然後只包含行(百萬或更多)的數量龐大的那些特定的表。不要盲目地全面應用「最佳做法」。

  3. 另一種方法是簡單地沒有包含數百萬行的事務表。在數據增長到這種比例之前將數據移到檔案表中。

1

DELETE在關係數據庫中的問題是它們是不可轉換的。你刪除數據,它已經消失了。沒有辦法恢復它(除了回滾到較早的備份,當然)。結合基於「我不明確排除所有內容」原則的SQL語法,這很容易導致由於用戶錯誤或錯誤導致的數據意外丟失。

只是將數據標記爲已刪除但未實際刪除它的優點是刪除的數據可以輕鬆恢復。但是,請記住,所標記爲刪除的模式也有缺點:

  • 正如你所說,編程變得更復雜一點,因爲你必須記住每SELECT現在必須包括WHERE deleted = false
  • 當你經常刪除數據時,你的數據庫會積累大量的內容。這會導致它增長,影響性能並使用不必要的驅動器空間。
  • 當您的用戶因隱私法規而被迫刪除數據時,他們認爲按下「刪除」按鈕確實會將其刪除,但這種做法可能會導致他們違反這些規定。
+1

我認爲可更新的視圖可能有助於解決問題1,儘管我沒有親自嘗試過使用MySQL。 –

+0

用於編寫我想寫的所有內容,但速度更快:) – flup

1

此問題有多個圖層。一般來說,將行標記爲已刪除而非實際刪除它是一個好主意。

有幾個主要好處:

  1. 的數據是可恢復的。您可以向用戶提供一個取消刪除。
  2. 該更新比刪除更快。
  3. 在一個面向公衆的應用程序中,沒有一個公共交互代碼具有真正的刪除,使得使用該代碼出於不適當的目的更加困難(sql注入等)
  4. 如果您曾想要報告數據您可以。

當然也有注意事項和最佳做法:

  1. 這並不適用,方便重新創建數據查找表。
  2. 你需要考慮撲殺。在我們的數據庫中,我們將刪除的記錄篩選到檔案報告表中。這使主錶快速,但允許我們報告與「已刪除」項目有關的數據。
  3. 您的撲殺性能影響(以較大規模)將類似於備份並具有類似的考慮因素。如果你想一次存檔所有的數據,或者通過cron定期存儲數小時的數據,如果你想每小時只需要X個數字就可以運行。
  4. 從不使用您的實時數據中刪除的數據。換句話說,它不是一個狀態標誌!這是不見了。我之前犯過這個錯誤,並且解開它是痛苦的。
  5. 如果表中刪除的百分比非常高,請問問自己是否保留數據非常重要。您可能會調整您的剔除過程而不進行存檔,而只是運行實際的刪除。

這種方法將持續非常長的時間,除非您的數據集很大並且刪除量很大。一些建築宇航員會問你,當你存檔10億行時會發生什麼......當你達到那個程度時,你要麼非常成功,要麼找到另一種方式,要麼你已經把其他東西完全搞砸了歸檔任務相對於其他問題無關緊要。