Iv'e只是从同事听说,一个关系数据库删除行是非常危险的(关于索引和级联动作)关系数据库 - 删除还是不删除?
他说,允许删除一个解决方案是有一个“过时”字段为每个实体而是将该字段设置为true以将该行标记为“已删除”。
当然,这需要您在所有的查询来获取所有的“专用” ==假(这是相当麻烦的)
我的问题是:
- 他是正确的?如果是的话 - 究竟删除究竟有什么危险?
- 他的解决方案是一个很好的做法吗?
- 此解决方案的任何替代方法都可用?
谢谢。
Iv'e只是从同事听说,一个关系数据库删除行是非常危险的(关于索引和级联动作)关系数据库 - 删除还是不删除?
他说,允许删除一个解决方案是有一个“过时”字段为每个实体而是将该字段设置为true以将该行标记为“已删除”。
当然,这需要您在所有的查询来获取所有的“专用” ==假(这是相当麻烦的)
我的问题是:
谢谢。
如果您的架构结构合理,并且在需要时使用事务,删除操作非常安全,并且使用删除操作,您的性能将远远优于您的朋友所建议的方法。
插入一个新元素可能会变得棘手,因为要删除一个元素。我想知道你的朋友建议如何解决这个问题。
CRUD操作在这里已经有很长时间了,关系数据库的创建者在优化它们方面做得很好。任何试图用这种黑客来胜过几十年的逐步改进的尝试很可能会失败。
应用您的朋友建议的解决方案可能会导致拥有庞大的数据库,只有一小部分未删除的元素。这样你的查询也会变得更慢。
现在说了所有我想支持一点点的另一边。有些情况下,您的朋友建议的解决方案可能是唯一的选择。每当某些查询变慢时,您无法更改模式。另外,正如其他人在他们的答案中所建议的,如果您使用“标记为已删除”的方法,删除的数据将可以恢复(在其他答案中可能会再次提及,也可能不会再好)。
不一定意见不一,但为什么它会提供更好的性能来删除? MySQL中缺少过滤索引? –
我拥有在大型表格中大量减缓批次删除的第一手经验。 –
你确定它不是造成这种缓慢的数据库结构? –
危险?服务器或数据中心会爆炸吗?
我认为你的同事沉迷于一些夸张。
如果你不想要,你不需要级联更新或删除,但它比手动清理更容易。这是您在创建模式时所做的选择。
将行标记为使用标记进行删除是另一种方式,但这只是另一种选择。您必须更努力地查找所有不良行并运行批处理作业以将其删除。
如果您有保留要求,对模式进行分区并将较旧的记录移入仓库进行历史分析和报告更为典型。在这种情况下,您不会删除任何内容,只需在一段时间后将其移出即可。
是的,他是对的。数据库(特别是索引)针对插入和删除进行了优化,可能会非常缓慢。即使将索引字段设置为空也会导致相同的问题。我看到级联是一个较小的问题,因为数据库不应该被配置为自动执行危险的级联。
是的,将记录标记为“不活动”,“删除”,“不推荐”(您的选择)是解决删除相关性能问题的标准和首选实践。
不过,晋级以上,它只适用于事务(相对于档案)表,然后只包含行(百万或更多)的数量庞大的那些特定的表。不要盲目地全面应用“最佳做法”。
另一种方法是简单地没有包含数百万行的事务表。在数据增长到这种比例之前将数据移到档案表中。
DELETE
在关系数据库中的问题是它们是不可转换的。你删除数据,它已经消失了。没有办法恢复它(除了回滚到较早的备份,当然)。结合基于“我不明确排除所有内容”原则的SQL语法,这很容易导致由于用户错误或错误导致的数据意外丢失。
只是将数据标记为已删除但未实际删除它的优点是删除的数据可以轻松恢复。但是,请记住,所标记为删除的模式也有缺点:
SELECT
现在必须包括WHERE deleted = false
。我认为可更新的视图可能有助于解决问题1,尽管我没有亲自尝试过使用MySQL。 –
用于编写我想写的所有内容,但速度更快:) – flup
此问题有多个图层。一般来说,将行标记为已删除而非实际删除它是一个好主意。
有几个主要好处:
当然也有注意事项和最佳做法:
这种方法将持续非常长的时间,除非您的数据集很大并且删除量很大。一些建筑宇航员会问你,当你存档10亿行时会发生什么......当你达到那个程度时,你要么非常成功,要么找到另一种方式,要么你已经把其他东西完全搞砸了归档任务相对于其他问题无关紧要。
http://stackoverflow.com/a/820489/477878 –