[外键应不应该建立]
和 manager 讨论外键应不应该建立,意见有点不一致
应用表是在 relation 上
对应外键在 user 及 resource 表内
因为整个公司项目都是伪删除,他主张不建立
但是我想着如果时间过长,太久没删除的数据会导致数据量越来越庞大,想使用 CASCADE 一并删除部分超过 3 年的数据
和 manager 讨论外键应不应该建立,意见有点不一致
应用表是在 relation 上
对应外键在 user 及 resource 表内
因为整个公司项目都是伪删除,他主张不建立
但是我想着如果时间过长,太久没删除的数据会导致数据量越来越庞大,想使用 CASCADE 一并删除部分超过 3 年的数据
完全没必要
你说的脏数据用另外的方案去删
如果从 DDD 设计的角度看,如果 Domain 模型也按这样划分,将一个 Bounded Context 以的 Domain 关系为强关联,不同的 Context 之间用 Ref 不用强制关联。
一个设计上考量,划分 BoundedContext 时,看一个核心 Domain 对象( DDD 中的 AggregateRoot )的 [ [生命周期] ] 依赖关系,比如 Customer,Order 位于不同的 Context,但是 Order 会记录 Customer,用 Ref ( Context Map )而不用强关联,而 Order 内的 OrderLine 等依赖一个具体的 OrderID,全部强关联。
另:个人不喜欢外键,但是挺喜欢用 JPA,JPA 创建关联关系时默认创建了外键,懒得填不生成外键的骚操作的注解或者改源码。导致 现在已经看淡了,只要能满足业务,都无所谓!!!
FK 只是数据库层面的约束,对于 ORM 框架来说,只需要知道根据哪个字段去处理就可以,这个字段不一定非要是 FK 的呀
就说一个巨常见的需求:不掉线改表。有的时候真的只能重建表结构,然后数据复制过去,然后改表名字。
如果你做了强制关联外键,恭喜发财。会遇到各种改不动
如果缺少做决策的人,或者经验不足衡量不了,建议按最简原则来施行。
更高的要求是在你们有足够经验或者目标明确的情况下,自然而然的过渡,不要过度设计。
—
以我的观察,现在网上的论调大多是不建议使用,这无可厚非:
因为现在互联网环境提倡快速迭代开发,而不是早年软件工程那一套需要开发后持续长期稳定维护更新的工作流程,所以各种范式约束反而会成为累赘。
—
但也不是说软件工程、范式那一套就没用,只是说需要用的人基本都可以自己确认,来问的大多是不需要用的,做决策者心里要有一把尺。
反范式的设计有时避免不了,JPA 继承的 JOINED 策略也违反数据库设计范式。以前在企业用户开发时,我特别喜欢全部建立数据外键关联关系,因为用一些 Stateful 的框架,比如,我用了两年 JBoss Seam,可以自行调节 FlushMode,跑一个 Conversation,跨多个页面,读取关联数据完全不用担心 Lazy Load 的问题,保存关联对象也很容易。但是到了一些 Stateless 的框架,比如当时的 SpringMVC,数据跑到 View 层,必须开启 View In Session 或者在进入 View 之前转换,各种关联在页面太令人头痛。Spring WebFlow 为了对抗 Seam,火了一段时间,现在这个项目也没在更新了。
DDD 中 BoundedContext 处理跨 Domain 的关联问题用一种比较折中的方式,比如用一个 Ref 类来记录 Order 中 Customer,即 CustomerRef (仅包括一个 ID 等唯一标志,对应到 Order 表就是记录一个 CUSTID,但不建立外键关联),Order,Customer 两个不同的 Domain 有自己生命周期,互不干扰。但 OrderLineItem 与 Order 是存在同一个生命周期内的,前者不能孤立存在,他们在表结构是外键关联。
你说的外键可以一键删除所有关联对象的好处,没外键又不是不能删除,还可以分批删除而不是在一个巨大事务中一次删除。
@love 主说的是,他们经理因为伪删除原因而“主张不建立”,这显然指的是不建外键,而不是再说级联选项。主的意图是在使用外键的同时使用级联选项,哪里读错了?
难道你认为我说的“关系型的优点”就是级联?
平心而论,国内的文档水平是什么层次大家都清楚的吧!国内人员流动率高低如何大家也都心知肚明的吧?我就说一个大家都司空见惯的场景吧:
某人新入了一个团队 /公司 /项目组,接手了别人一个库,数百张没有关系的表,没文档,甚至表名还有可能是汉语拼音缩写,只有团队里为数不多的“老师傅”才知道每个表是干什么的——这时候唯一能做的事情就是花上巨大的时间消耗,通过观看生产数据,脑补,重构关系,对不对?
要是有外键,何苦来载?
嗯,然后自己也不建外键,把这份痛苦留下后一波接盘的吧!
其实上面也有人说,互联网项目不喜欢用外键,其实原因根本不是什么性能啊——有谁是在发现了性能不够之后删除外键来改善的吗?才没有呢,都是从一开始就不建的。为嘛啊?因为互联网项目迭代快,死的也快,上面举例那种场景不构成痛点罢了!
2.不用外键,也能达到这个目的,方法有很多。比如在后端代码里处理,或者在中间件里处理。
3.个人开发或研究,在前期数据了不大的情况下,为了快捷方便,可以使用外键,来提高开发或研究速度。
4.团队协作,或者个人开发但数据量大,不建议用外键。
承认这一点没什么关系, 然后大大方方扬长避短不用外键就可以. 但是以此来声称数据库处理不好关联关系, 有坑, 不如自己在业务代码里的实现完美, 这就有点搞笑了, 数据库是个很成熟的领域, 几十年来各种研究论文工程实现汗牛充栋, 要说比不过大部分国内互联网大中小厂子的三板斧实现, 我是不信的.
即使你不用外键, 数据不一致最终也要处理, 只不过是怎么处理而已.
一句话,可能影响业务,少个外键又没有实际损失。
不要!
有一部分回复是支持“在恰当的场景下使用外键”,前提条件是需求明确。
另一部分人的口吻是“弊大于利不用”。但实际上主张弊大于利的,我感受了一下,其实有个前提条件,是一开始的需求没那么明确,还要充分迭代开发,导致后面原先的外键变成了累赘。
你们两拨人根本讨论问题的前提条件就不一样好吧。
很多年我工作中不再具体的关心数据库了,有时都是几种数据库混合,现在用单一数据库的情况反而太少,合适的场景用合适的数据库(包含 RDBMS,NoSQL 了)。
我一直主张 Java 要以 Domain 为出发点分析业务,才符合 OOP 基本特性,所以我 10 几年做的项目中,也没有所谓的数据建模这一步,也不会有所谓的数据库设计文档,因为整个开发过程根本就不用关心过数据库里面是怎么保存,怎么读取的。
主的伪删除需求我觉得对用不用外键影响不大。伪删除的目的就是永久保存吧,只不过可以保存在别的地方。
高开发效率:建立外键,自动删除,新旧数据同时存放;
高安全:不建立外键(防止 CASCADE 自动删除),禁止账号删除权限(只做软删除),新旧数据同时存放;
如果你是领导,你选哪个方案?
我选择 3,只在需要时候才迁移无效数据作为补充。
我相信上面讨论的人也有这些情况,有些人用了功能完备的 ORM,所以哪里需要用到什么外键啊。另一些人对着数据库就是一阵手撸,说不定建表还是 phpMyAdmin 建的,对这些人来说外键的作用就会大很多。
正因为可以 orm,所以选 3 。。。