在设计一个新系统的Table Schema的时候,不仅需要满足业务逻辑的复杂需求,而且需要考虑如何设计schema才能更快的更新和查询数据,减少维护成本。

模拟一个场景,有如下Table Schema:

Product(ID,Name,Description)

在设计思路上,ID是自增的Identity字段,用以唯一标识一个Product;在业务逻辑上要求Name字段是唯一的,通过Name能够确定一个Product。业务上和设计上有所冲突在所难免,解决冲突的方法其实很简单:将ID字段做主键,并创建clustered index;在Name字段上创建唯一约束,保证Product Name是唯一的。

这样的Table Schema 设计看似完美:ID字段具有做clustered index的天赋:窄类型,自增,不会改变;Name上的唯一约束,能够满足业务逻辑上的需求。但是,如果业务人员操作失误,将Product 的 Name 写错,需要将其删除,最简单的方式是使用delete 命令,直接将数据行删除,但是这种方式带来的隐患特别大:如果业务人员一不小心将重要的数据删除,那么,恢复数据的成本可能非常高。如果数据库很大,仅仅为恢复一条数据,可能需要N个小时执行还原操作。如何设计Table Schema,才能避免在维护系统时出现被动的情况?

delete Product
where Name='xxx'

设计目的:在短时间内恢复被误删除的数据,以使系统尽快恢复

在实际的产品环境中,数据删除操作有两种方式:软删除和硬删除,也称作Logic Delete 和 Physical Delete。硬删除是指使用delete命令,从table中直接删除数据行;软删除是在Table Schema中增加一个bit类型的column:IsDeleted,默认值是0,设置IsDeleted=1,表示该数据行在逻辑上是已删除的。

Product(ID,Name,Content,IsDeleted,DeletedBy)

软删除实际上是一个Update 操作,将IsDeleted字段更新为1,在逻辑上将数据删除,并没有将数据行从物理上删除。使用软删除,能够保留有限的数据删除的历史记录,以便audit,但是,这可能导致外键关系引用被逻辑删除的数据;如果历史记录太多,这又会导致数据表中有效数据行的密度降低,降低查询速度。

1,能够快速恢复被误删除的数据

用户的删除操作是将IsDeleted设置为1,在逻辑上表示删除数据,如果用户由于误操作,将重要数据行删除,那么只需要将IsDeleted重置为0,就能恢复数据。

update Product
set IsDeleted=1
where Name='xxx'  -- or  use ID=yyyy as filter

2,每次引用该表时,必须设置filter

任何引用该表的查询语句中,必须设置Filter:IsDeleted=0,为来避免遗漏filter,可以创建视图,不直接引用该表,而是直接引用视图。

--view definition
select ID,Name,Content
from Product
where IsDeleted=0

3,手动处理外键关系

如果在该表上创建外键关系,那么可能存在外键关系引用被逻辑删除的数据,造成数据的不一致性,这可能是很难发现的bug:如果需要保持关键关系的一致性,需要做特殊的处理。在将数据行逻辑删除之时,必须在一个事务中,将外键关系全部删除。

4,不能被用作历史表

数据表是用来存储数据的,不是用来用户操作的历史记录。如果需要存储用户操作的历史记录,必须使用另外一个HistoryOperation来存储。

上述Product表中Name字段上存在一个唯一约束,如果用户将相同Name的Product重新插入到table中,Insert 操作因为违反唯一约束而失败,针对这种情况,软删除操作必须额外进行一次判断:

if exists(select null from Product where name ='xxx' and IsDeleted=1
)
update set IsDeleted=0,...
from Product
where name ='xxx' and IsDeleted=1
else
insert Product(...)
values(....)

如果Product表的数据量十分大,额外的查询操作,会增加插入操作的延迟,同时,"无效"的历史数据降充斥在数据表中,也会降低数据查询的速度。

单纯从业务需求上考虑,软删是首选的design,定期清理软删的冗余数据,也可以提高数据查询的速度,不过,在清理数据时,可能会产生大量的索引碎片,造成并发性降低等问题。

5,将删除的数据存储到History表

使用软删除设计,增加IsDelete=1 字段,实际上降低了有效数据的密度,在使用软删除时,必须慎重考虑这一点。改进的删除数据的设计是:在一个事务中,将删除的数据存储到另外一个History表中。

delete from Product
output deleted.ID,deleted.Name,deleted.Content,'Delete' as CommandType '' as UpdatedBy,getdate() as UpdatedTime
into History_table
where Name ='xxx' -- or use Id=yyy as filter

恢复误删的数据,只需要到History表找到相应的数据,将其重新插入到Prodcut 表中,并且,History 表中不仅可以存储用户删除操作的历史记录,而且可以存储用户更新的历史记录,对于系统的维护,解决用户纠纷和故障排除,十分有帮助。

Product(ID,Name,Content)
OperationHistory(ID,ProductID,ProductName,ProductContent,CommandType,UpdatedBy,UpdatedTime)

为设计Product 表的删除操作,需要两个Table,对于OperationHistory表,可以做的更通用一些。抛砖引玉,提供一个思路,我就不做扩展了。

作者:悦光阴
出处:http://www.cnblogs.com/ljhdo/
本文版权归作者和博客园所有,欢迎转载,但未经作者同意,必须保留此段声明,且在文章页面醒目位置显示原文连接,否则保留追究法律责任的权利。

分类: SQL Server
标签: 软删除, 逻辑删除
本文转自悦光阴博客园博客,原文链接:http://www.cnblogs.com/ljhdo/p/5792886.html,如需转载请自行联系原作者

Design7:数据删除设计相关推荐

  1. Windows 8.1 重复数据删除——规划部署(二)

    一.规划部署目标    Windows 8.1&Server 2012 的重复数据删除设计为安装到主要数据卷上,而无需添加任何附加的专用硬件.这意味着你可以安装和使用该功能,而不会影响服务器上 ...

  2. 为什么集群要奇数_面试系列 redis数据删除amp;集群

    redis数据删除/内存淘汰 如果我们设置一批key只能存活1小时,那么1小时之后,redis是怎么对这批数据进行删除的? 答案:定期删数+惰性删除 (1)定期删除 指的是redis默认是每隔100m ...

  3. 一个页面区分管理者和普通用户如何设计_产品经理要做的操作权限/数据权限设计...

    产品经理在工作中还需要知道一个:用户权限设计能力.权限设计理念贯穿于后台产品.以及用户前端产品. 权限能力包括两类:数据权限.系统操作权限 有的人会好奇,为什么前端产品会有有权限管理的要求?接下来我将 ...

  4. 重复数据删除将成标配功能

        因为嗓子发炎,Data Domain首席科学家及创始人李凯在回答记者提问时语速十分缓慢,但语气十分坚定:"创立Data Domain公司的初衷就是想寻找一种能够替代磁带的产品或解决方 ...

  5. 一个将当前目录下HEX文件的第一行数据删除的程序...

    为什么要写这样一个函数 在使用SoftConsole开发M3程序时,生成的hex文件,必须要把第一行数据删除,才能在Libero中使用,所以写了这个小工具,这是2.0版本了,第一版是直接删除第一行数据 ...

  6. 大数据可视化设计到底是啥,该怎么用

    大数据可视化是个热门话题,在信息安全领域,也由于很多企业希望将大数据转化为信息可视化呈现的各种形式,以便获得更深的洞察力.更好的决策力以及更强的自动化处理能力,数据可视化已经成为网络安全技术的一个重要 ...

  7. 是先设计mysql表再进行php代码_PHP与RBAC设计思路,数据表设计与源码讲解

    权限系统模块对于互联网产品是一个非常重要的功能,可以控制不同的角色合理的访问不同的资源从而达到安全访问的作用 权限控制有哪些模型ACL RBAC 基于角色的访问控制 从上图我们可以看出,ACL是用户和 ...

  8. 删库不必跑路,谈数据库删除设计

    作者:杜哥 原文链接:https://my.oschina.net/yangyishe/blog/3138204 1 常见删除策略 凡是做业务逻辑系统, 总是离不开对删除逻辑的处理. 本文论述重点是伪 ...

  9. 8000 字深度长文!B端数据可视化设计指南(信息图表篇)

    作者:核糖Bro(转载已取得作者授权) 在如今的工作中(尤其是 B 端)越来越多的会开始出现数据可视化的身影,对于一部分小伙伴来说这个概念是较为陌生的,面对这道无形之中提升的"门槛" ...

最新文章

  1. c语言怎么创建一个h文件,求助C语言大佬 , 只会写到一个.c文件里 ,不会用.h头文件...
  2. jquery ajax中使用jsonp的限制[转]
  3. c#图像灰度化、灰度反转、二值化
  4. vue npm: react运行时报错npm start — babel-eslint 版本兼容性问题
  5. 近似线性依靠matlab_不要仅仅依靠单元测试
  6. pin controller driver代码分析
  7. 数据归一化处理方法_科研常用的实验数据分析与处理方法
  8. setstate是同步还是异步_谈谈 IO模型:同步、异步、阻塞、非阻塞
  9. ELK系列~NLog.Targets.Fluentd到达如何通过tcp发到fluentd
  10. Oracle JDK收费理解
  11. FPGA学习.7——DDS信号发生器
  12. AE/PR模板:10组电影质感海报宣传文字标题设计动画Cinematic Titles
  13. 小张初识c语言的成长经历NO.1
  14. 【2389. 和有限的最长子序列】
  15. python地图gps轨迹可视化_GPS轨迹数据可视化的三种途径
  16. android is not translated in 报错解决方案
  17. Rainbow 开发 step1
  18. SimpleMind Pro中文版
  19. 昨天,中国首座跨地震断层跨海桥梁通车
  20. 计算机中shell是干什么的

热门文章

  1. Tips--Anaconda安装TensorFlow报错ImportError: DLL load failed
  2. MobSF,一款开源移动安全测试框架
  3. 项目部署—移除Spring Boot内置Tomcat,部署到云服务器Tomcat
  4. linux哪个系统能编译固件,rk3328编译Linux固件
  5. 计算机打印中 进纸盘2,软件、计算机和打印机接口问题-HP.PDF
  6. 加油卡 格式判断 java_JAVA实验_题目8
  7. 不想用鸿蒙系统怎么办,华为鸿蒙系统出大BUG!网友:这再也不是用户想要的鸿蒙系统...
  8. CDH spark2切换成anaconda3的问题
  9. [LOJ#6053]简单的函数 题解
  10. Go学习笔记(一)windows下的Go 语言环境安装,并运行第一个Hello World程序