是什么理由让你彻底抛弃数据库的外键?

2016-11-22 14:28:29 +08:00
 ljk

初涉后台开发未深,诚惶诚恐看 <SQL 反模式>,学习最佳实践。

发现现在这个项目应用了不少反模式,其中最让我困惑的是,完全不使用外键,涉及到外键的逻辑全部在应用代码里实现。

询问项目负责人,告知不使用数据库外键主要有两原因:

  1. 多台服务器不停机升级时,有可能数据库新加入的外键限制导致新程序没办法在旧数据库上跑
  2. 运维人员对数据库外键深恶痛绝(举例说唯品会就是这样做的)

听起来只要是分布式的服务器热升级(第一点原因)、或者团队里有运维人员,就应该抛弃数据库外键了。

业界都是这样做的吗?书上说的当真脱离了实际?

谢不吝赐教。

25538 次点击
所在节点    程序员
117 条回复
pangliang
2016-11-22 16:53:27 +08:00
约束在表结构里,
那逻辑变动 约束就会变动,
而 约束变动, 表结构就要变动
而表结构变动, 就要死人
Midnight
2016-11-22 16:57:47 +08:00
所谓的抛弃外键不是说连关系都不要了,只是没有在表上建外键这个属性,场景不同方案不同啦,分布式的话有外键同步会很麻烦,单数据库应用就无所谓啦
mko0okmko0
2016-11-22 17:14:14 +08:00
没抛弃过,但如果不用外键甚至不用拆表我就满足了性能,体积,设计复杂度.我何必用外键?
应该说,我何必用传统标准资料库?

例如 TokuDB,这是 Mysql 体系可选用的一个核心.本身是列式仓储.具有资料本身就是索引,结构本身就是有压缩的树状仓储.用了它,很多拆表的意义就没了.没有拆表何来外键?

例如 XML/json 文档式资料库.保持了包含关系也不需要序列号,每份文档的位置都已经代表他自己.或是每个 KEY 跟 VALUE 在资料库底层都已经有他自己的唯一值了.
而且文档资料库还解决了相同目标栏位不同内容物的问题,

标准资料库如果相同栏位要放不同子表的内容,设计上你会想死.
如果唯一键不是数字,又要给该表一个序列号,这样有比较省吗?各方面大都没有.

将标准资料库 /nosql 资料库一起比较关联查询,为什么这样说?因为就是有需求阿,尤其初期就没考虑到的东西突然发现要查他们关联后的条件查询结果.尤其是其中有些表没有序列号了,关联的值就是用文字.

那时候都有性能一样低下的问题.....一样低下的结果,那又何必分有拆表没拆表?有序列号没序列号?

用过更好的解决办法,你还会回头用标准资料库或是放弃更好的非标准资料库吗?

以上工作实务经验,依照每个人经验不同应该会有不同的解答,以上纯分享.
tumbzzc
2016-11-22 17:18:19 +08:00
以用 flask 写网站为例,逻辑都是自己写的,没必要用外键
hyuwang
2016-11-22 17:21:06 +08:00
@ljk 不是专业后端,从运维角度来说的,我数据库开发经验不多,我个人是不会在写入数据时候做效验的,我只会效验数据本身,然后写好测试,测试能跑通的数据验证过了就好
akira
2016-11-22 17:26:53 +08:00
不用外键
少用存过
少用特定数据库特定版本才有的特性
z5864703
2016-11-22 17:54:04 +08:00
为什么一定要用数据库的外键,改动还麻烦。
在程序业务逻辑中实现外键约束,可以灵活很多
tonghuashuai
2016-11-22 18:03:51 +08:00
除了在大学里用过外键,实际工作中在设计数据库结构的时候都不约而同的不适用外键(一个眼神就不约而同了),外键的好处可能有很多,但是外键的不好你遇到过几次就会彻底抛弃它,改用逻辑约束。
Felldeadbird
2016-11-22 18:05:50 +08:00
用过外键,然后测试时发现数据特别麻烦,而且又不是一定要严格的模式,就没理他了
jianghu52
2016-11-22 18:42:00 +08:00
当初我们设计新系统的时候,还就要不要外键做过争论。我们的项目是 PHP+mysql 。
开始我属于强烈要求用外键的。在不考虑分库的情况下,外键的制约可以有效的让项目人员不用测那些奇葩的数据。(即业务之内不可能出现的那种)。另外就是,外键的存在在很大程度上让我们设计库的时候尽可能的多思考项目扩展的问题,如果没有外键的话,很多时候设计数据库就是有什么业务就设计成什么样子,很少考虑后期业务增加的时候,数据库是否容易扩展的问题。事实上因为我们最后选择了无外键的数据库设计,这些问题在后期都爆发了。当然,最后我也没办法袖手旁观,该填的坑还是得填。
跟我针锋相对的一个同事他的观点也很容易理解,在要求开发速度的情况下,外键不仅是一个困扰,更加是一种折磨。为什么这么说,越是严谨的外键设计,你在做测试的时候前置工作越多,越浪费时间不说,很多时候当你只想测试某一个小部分的业务逻辑的时候,你不得不从头开始填入数据库的表,你吭哧吭哧的花了半小时填了 5 个表,仅仅只为了测试其中的一个字段。这种花费在我们那时看来确实有点太大了。
另外外键还有一个隐性的成本,就是教学成本。这是我的一点经历。以前有个项目进了一个新人,我负责给他培训。当时的业务还不算复杂,我给他讲的时候,对外键讲的也不是很细,就告诉他如果表有这样的字段的话,那么程序会如何如何显示。结果等他下课自己做的时候,就发现动不动就是这个表插不进去,然后就要去看关联的外键是什么,之后又一堆找关联的表的字段信息,该插入什么样的数据。
往往一小段程序,会关联出很大一块儿的业务,你给他讲吧。他也不能马上就全记住,浪费时间。不给他讲吧,你就得给他做好前置的数据准备工作,也得花时间。
我到现在决定,外键适合那种不太大的业务,配上严谨的文档,严格的开发流程的团队。可惜我现在做的项目,只跟项目大小沾边,后面几个条件完全无法满足。
zhouquanbest
2016-11-22 19:04:01 +08:00
我的理解是 数据库只做“存储” 因此外键的逻辑 就应该放到代码里
没了外键 你发现分布式啥的都舒服了 天下太平
没了外键 你发现重构成本降低了 再也不怕 PM 改改改
没了外键 你发现如果每张表都设计了冗余字段 把外键提供的信息多存一份逻辑反而更简单性能更好了
cjyang1128
2016-11-22 19:06:58 +08:00
对于大的系统来说,能不用外键就不用外键,全靠代码逻辑,好定位 BUG !!!
codeyung
2016-11-22 19:08:55 +08:00
目前做的 没有在用外键 都是逻辑 和 中间表 做的 - -
heww
2016-11-22 19:11:52 +08:00
看了上面好多人的项目一上来就是好几百亿的项目!
xiaowangge
2016-11-22 19:33:05 +08:00
游戏行业的路过,几乎连数据库( MySQL )都不在用的。

凡是能用 Memcached (腾讯云的 Memcached 的可落地永久存储),就不用 MySQL 。
anubiskong
2016-11-22 19:47:01 +08:00
其实是个很简单的道理
外键就是程序逻辑, 逻辑应该都放在一起, 以方便维护, 当然是和程序放在一起才合理, 更何况程序还有更高的灵活性
唯一例外的情况就是巨大的性能差异或者是代码维护方面的成本上的差异, 而这两个例外在外键这个简单需求上没有体现.
数据层面的东西层级越少越好, 关系越少越好, 必要时为了性能适当的冗余数据, 用硬盘换性能
很多系统在设计上有历史包袱, 有些陈旧的东西不应该再想太多, 尤其是 php 和 mysql 这种很普及但上年纪的产品
hheedat
2016-11-22 19:47:31 +08:00
DBA 不让用, 666
movtoy
2016-11-22 20:22:55 +08:00
根据自身情况呗,

人家阿里有公关部,我开个豆腐店也要么
lightening
2016-11-22 20:32:23 +08:00
@SpicyCat 我想是指在 ORM (你的代码) 里实现,而不用数据库内置的外键约束。
lightening
2016-11-22 20:38:41 +08:00
我个人来说,是因为 ORM 本来就提供了约束,而且使用非常方便。没有必要的理由的话,我没必要加外键约束。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/322370

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX