大家用 mysql 做项目的时候,是否用外键呢?

2014-08-20 18:38:32 +08:00
 gkiwi
目前公司倾向于用外键.个人倾向于不用外键,而将约束控制变更到代码逻辑里面进行控制(其实即使用了外键,该判断的大多还是会有的):

个人关于不用外键的理解:
1.方便模型的变更.(由模型导成sql,然后进行重建表很方便,而加上外键单独重建表只能挨个字段改了CRUD更方便)
2.性能会更好些

这里有篇文章介绍的文章http://www.cnblogs.com/tearer/archive/2010/07/25/1784896.html
===
求各抒己见.
8122 次点击
所在节点    程序员
33 条回复
est
2014-08-21 09:57:24 +08:00
项目变得快就不用。

需要级联删除的就用。
lyazure
2014-08-21 11:10:36 +08:00
@mengzhuo

不喜欢用外键的人,应该比较经常在数据库里手工操作数据和表结构吧,不能直接删不爽……不用外键删虽然能删了,删完后数据库里一堆断肢残臂真的好么……

用外键跟程序里能不能处理好逻辑关系不大,外键就是反映实体间引用包含关系,定义正确的外键跟定义正确的主键一样,反映了整个设计的逻辑合理性,是设计和实现人员的沟通工具

另外也可以把外键当做“施工保护”,避免有人对设计理解错误或者不小心弄出bug……

楼主说的两个理由:
1.模型变更,删除建立/启用禁用外键可以弄一组sql语句,对这种影响完整性的操作,可以先禁用或者删除,改完后再恢复,不过设计好模型之后,出现影响完整性的变更应该是比较少的
2.外键影响性能…………楼主真的遇到过这个情况吗?
gkiwi
2014-08-21 11:50:05 +08:00
@lyazure

现在刚开项目,模型变更比较大,所以改来改去很烦躁;
性能问题是道听途说的(也一直如此认为).刚刚搜了下(参照:http://www.xiaoxiaozi.com/2009/07/12/1158/),部分情况确实有性能问题,但在部分情况下却也会优化性能.在完整性上面有益处.

其实在线上运行时候,我并不反对有外键(性能问题我们还早着呢).但是在开发时候,外键会影响开发效率倒是真的.
knightluffy
2014-08-21 12:03:22 +08:00
ER图搞外键是可以的,但是开发的时候搞外键,感觉有点多余,有时候字段还没定下来删起来都麻烦,虽然不知道跟性能是否有挂钩。。
lijingyu68
2014-08-21 12:29:38 +08:00
设计的时候需要外键来表明表之间的关系,实际开发的时候就不用了。
lightening
2014-08-21 16:51:28 +08:00
@cxh116 哦,我知道了。这里说的是用 MySQL 的外键约束关系。我刚才想那个 int 字段不就叫做 foreign key 么。
cxh116
2014-08-21 17:13:53 +08:00
@lightening
比如 user_id 这个字段,没有加外键约束的时候,你可以把它设置为0,或设置为不存在的user的id

但如果加了外键约束,user_id的只能为user表里面有的数据的ID

Rails的关系字段在业务意义上来说是外键,但对数据库来说,就是一普通的int字段
Biwood
2014-08-21 21:16:49 +08:00
我对后台不是很熟,以前学.NET时听说过外键,还有三大范式、关系表什么的,我以为凡是设计数据库必须用到这些呢
lygmqkl
2014-08-21 22:32:49 +08:00
用代码来模拟FK 我直能说,你对数据还不够敏感,你写的代码再好能赶上数据库层的数据操作?

醒醒吧不要给自己找借口了,越是大的程序对数据完整性要求越高。

要是有300张表的项目,你算过你所谓的控制代码需要额外写多少吗?
就算是100张你算过数量级吗?
还有因此给团队管理带来的麻烦吗?
huobazi
2014-08-23 00:42:03 +08:00
@lygmqkl 表再多再多些,分布在不同数据库你就不这么认为了
looly
2014-08-23 14:05:31 +08:00
看需求。如果你做一个业务比较复杂,表之间关系也很复杂的项目,建议你用外键。用代码来保持数据的完整性会让你崩溃。例如你有一张学生表、学院表、学校表、城市表,依次关联,中间删一条数据你的下面的数据就全断了,数据就完全乱了。

但是,如果你做的项目就几张表,且关联很小(或者是弱关联),性能要求还很高,就不要用外键了。其实你看现在的nosql没有外键的概念,就是为了摆脱外键舒服,提高性能。
lygmqkl
2014-08-25 15:02:42 +08:00
@huobazi “吃人不吐骨头” 已经达到重构需求级别的项目?或许这种项目我没遇到过吧,但是我不觉得应该把这种放在一般项目开发或者常规项目开发的范畴内,你是不是有一点以偏概全了?
hunterhug
2019-05-18 12:50:44 +08:00
外键在某些情况必须用,否则你必须防止幻读,需要使用最强事务隔离,序列化隔离来做级联。

比如有两张表:爸爸表和儿子表,儿子的表带上了爸爸的 ID,是外键,但是你没用这个关键字。

你开启了事务 1:

删除老爸
删除儿子们

提交事务 1

你在另外一个窗口开启了事务 2:

查询老爸(因为事务 2 是事务 1 提交前进入的,就算事务 1 在之后 comit 了,但老爸在 MVCC 模式下可重复读)
插入儿子

提交事务 2

你会发现,老爸不见了,但是莫名其妙多了一个儿子出来。

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

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

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

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

© 2021 V2EX