在数据库设计中,当删除一条记录的时候,是加一个标记位还是直接删除这一行?
如题,就是当有人取消关注时候,是删除这一行还是,加一个标志位,标记一下已经删除了?这是否是一个数据库范式?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如题,就是当有人取消关注时候,是删除这一行还是,加一个标志位,标记一下已经删除了?这是否是一个数据库范式?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(9)
简单地说,看情况。
下面具体说说我的理解
“删除”指的是什么?弄清这个很重要。
“删除”(delete)一条记录,意思是把数据库表中的一行删掉,删掉后这条数据就没了。
客户“删除”(取消, cancel)了订单,意思是这个订单还在,只是状态变了。
这两个场景中“删除”的含义是不同的。第1个场景,delete是针对数据库的操作,是业务之外的概念;第2个场景,delete是业务范围里的概念。
所以,如果是业务需要,“软删除”,业务不需要,“物理删除”。
从数据库术语的角度看,删除指的是“物理删除”。“软删除”这个词起得很不好,容易误导人,因为实际上并没有删除。更贴切的词是“取消”,“归档”,等等。
“删除”的含义很广,如果混淆了概念,提问和回答都失去了准确性。大家各执一词,引经据典,最终还是没有结果。
关系数据库可以看成是一个信息系统,用来记录客观事实,用户或应用程序可以从这些事实中推导结论。数据库里的表(关系,relation)就像几何证明中的公理。因此,删除一条记录可以看成是改变了事实(客观状态)。
比如,有一张表 TeacherClass(TeacherName, ClassName)。
数据((张三, 1班), (李四,2班))的含义是:张三老师给1班教课,李四老师给2班教课。每条记录都是一个事实(“真值”)。
删除一条记录后成为((张三, 1班)),含义是:张三老师给1班教课,李四老师不给2班教课。“李四老师给2班教课”为假,因为(李四,2班)没有出现在表中。
所以,到底怎么“删除”,看情况。
哪些事实是需要记录的?如果客户“删除”订单是需要记录的事实,就用“软删除”(不是数据库层面的delete,而是业务范围的“取消”)。一个可行的设计是:
Customer(CustomerId)
Order(CustomerId, OrderId)
OrderStatus(CustomerId, OrderId, Timestamp, Status)
每个Customer可以有0-n个Order
每个Order可以有0-n个OrderStatus
用户取消订单,就在OrderStatus里添加一条记录(insert,不是delete,因为多了一个客观事实)
反之,如果业务不需要记录的“删除”就用“物理删除”
Person(PersonId, PersonName)
Hobby(HobbyId, HobbyName)
PersonHobby(PersonId, HobbyId)
每个Person有0-n个Hobby
每个Hobby被0-n个Person拥有
如果张三喜欢打篮球,过了些日子,不喜欢打篮球了,就应该从PersonHobby里delete一条数据。当然,前提是业务需求中不需要记录为什么删除。
关系数据库用来记录当前的客观事实,增、删、改,对应事实的改变。
有一种类型的表称为“history table”(或"audit table"),他们是专门用来记录历史数据的。通过trigger或存储过程实现。他们的功能跟其他表不同,他们记录的是对数据库的操作,不是业务范围的事实。history table通常数据量会随时间越来越大,它们没有删、改,只有增、查(少量的查),而current table中的数据量相对较小,正好满足业务需要(增、删、改、查)。
关于soft delete的好处,justjavac的介绍很棒。
不过是否应该使用soft delete,还是需要慎重考虑。
在关系型数据库中,软删除(soft delete)主要影响的是write的效率,而不是read,所以在这种情况下,考虑采用soft delete的可行性的时候,也要考虑你的table/database面对的是否是write intensive的需求。另外,采用soft delete,一般是为了可能的恢复,为了audit,为了保存历史数据等等目的。那么为了某个或者某些数据,是否soft delete真的是最好的处理方式呢?比如为了log的auditing,而对log采用soft delete,或许就有一些小题大做了。
而对于NoSQL数据库,软删除通常来讲是很容易接收的。尤其是Key-Value的NoSQL数据库,比如Amazon的Dynamo DB和Riak等等,实现原理是hash table,所以就算有大量的soft delete数据,也不会对性能造成巨大的影响。而对于其他类型的NoSQL数据库,Document-based(比如CouchDB)或者Column-based(比如hbase)等等,data integrity重要性也是远远超过采用soft delete带来的性能下降的。
我觉得还是加个标志位合适点,因为如果被删除的数据,以后要用于统计等,或者由于误删除的话,也可以回滚的;加标志位的缺点就是如果这些数据被删除以后不被用到了,那么随着数据量越来越大,数据冗余也越来越大,对于此表的更新和查询操作也会有性能上的影响。这是个人意见,不当之处请指正 :-)
显然都不好。
正确的方式是加入其它信息比如删除日期,然后移动到其他库里比如历史库。
一般数据是不会真的删除的,因为如果删除,后面如果出现一些问题的话就没法查询到底是那条数据出现了问题,所以一般都是会加上一个标志位。
小数据无所谓,看需求了
数据量大,最好另建一表保存删除数据
删除的很少用
你的问题可以用两个概念加以说明:
物理删除:真删除,数据消失。
逻辑删除:假删除,数据存在,只是用一个字段来标记该条数据“已删除”。
到底用物理删除还是逻辑删除需要看应用场景和客户需求了。
根据需求而定,以后基本不用的数据完全可以删除(可以采取缓冲处理,先标记,后在系统不忙时删除)节省空间,减少无用检索;另一种情况,数据以后可能被重复利用,则打上标记,空闲时移到历史库。