我应该使用外键吗? [复制]
Posted
技术标签:
【中文标题】我应该使用外键吗? [复制]【英文标题】:Should I use foreign keys? [duplicate] 【发布时间】:2010-10-10 14:15:19 【问题描述】:可能重复:What’s wrong with foreign keys?
我使用带有大约 4 GB 数据的大型数据库的 MS Sql Server。
我在网上搜索为什么我应该使用外键。 到目前为止,我只索引了用于连接表的键。 性能很好,数据完整性没问题。
我应该使用外键吗?使用外键会获得更高的性能吗?
【问题讨论】:
【参考方案1】:外键实际上并没有提高性能,实际上它们会在所有写入操作上产生很小的性能损失,以确保遵循约束。
您要使用这些的原因是为了防止破坏性的写入操作。如果您没有它们,错误代码或错误的 sql 语句可能会删除预期存在的行。
【讨论】:
FK 无法保护您免受不良代码的侵害。如果有依赖的孩子,它们只能保护您免于删除外键关系的父端。【参考方案2】:诚信今天可能不是问题,但正是这种态度会在明天或两周后成为问题。
【讨论】:
【参考方案3】:外键主要是用于加强数据库完整性的工具,与执行速度无关。
如果您已经优化了索引设计,那么您可能已经安装了这些索引,至少作为非唯一索引。所以我不希望仅仅通过安装外键来改变性能(甚至不一定涉及索引。)
不过,如果您还没有明确这个概念,我会有点怀疑您对优化设计的自满。
阅读有关外键的文档,以了解它们为强制完整性所做的工作(无论如何都值得了解。)然后看看这是否不能更完整地回答您的问题。
【讨论】:
“与执行速度无关”对于插入并不完全准确(我知道你知道,但 Tuan 可能不知道) Thx - 我填写了一些答案,以一种应该在同一个地方结束的方式。 关于插入的好论据。我对结构有很好的看法。正如我所说,诚信没问题。我需要原始速度。【参考方案4】:SquareCog 之前链接到的旧问题中没有提到的问题 - 是的,外键约束在进行数据清理、批量更新、测试数据生成或任何类型的绕过正常序列的操作时可能会很痛苦事物。但是 - 在你做这样的事情之前,你总是可以删除你的外键约束,然后再重新创建它们(如果你的数据库对象脚本正确,这几乎没有任何额外的工作)。
我曾经很懒惰,但已经开始依赖外键约束。在某些情况下您仍然无法拥有它们 - 例如在跨数据库关系中。
【讨论】:
【参考方案5】:外键为您的系统带来了一项功能/约束,目前尚未提及。那是提交/事务逻辑(这就是我所说的)。在启用外键的情况下,所有受影响的表中的所有更新行都需要在那里才能进行提交(不要抛出违反外键约束的 SQL 错误)。
如果您有一个代码体,它可以工作并且“快速而松散地”,带有提交/事务。然后您可以进行一些补救,以使架构中的 FK 能够正常工作。
此外,至少 Oracle 允许您禁用约束(不仅仅是删除/删除)。因此,您可以轻松地打开/关闭它们。方便,当您想在没有约束开销的情况下进行一些批量操作,或者对具有可能使约束失效的中间状态的数据进行一些“手术”时。
【讨论】:
我发布的链接中提到了这两个,但无论如何我都会投票给你。 “提交/事务逻辑”正式称为 ACID 保证(“C”表示一致,如事务完成后数据与声明的约束一致)。【参考方案6】:在 mysql 中,您可以使用 SET FOREIGN_KEY_CHECKS=0
禁用外键
【讨论】:
【参考方案7】:外键还有助于保持数据库清洁,因为您可以让数据库进行级联删除。
【讨论】:
【参考方案8】:外键可提高数据完整性和性能,但在删除/插入/更新时会稍慢。 在我上一家公司,我们决定在 BL 中保持完整性/连接,因为它使 BL 中的更改更简单(想想数亿条记录)。如果您有一个小应用程序,我认为没有理由不在数据层(db)中做它
【讨论】:
BL 代表什么? 业务层,数据层处理直接与数据库对话的代码。 BL 获取该数据并使用该数据实现业务规则,并将其发送到 UI。这是查看多层软件的一种旧方法。今天,我们有超过三层/层,并且我们有广泛分布的系统可以添加到此。 通过说“我们决定在 BL 中保持完整性/连接”,您是指代码优先方法还是其他方法? “我们”指的是软件架构师团队。但是,如果我理解您的问题,那么是的,我们通过代码本身而不是在数据库中维护数据的完整性。顺便说一句,我并不是说/声称这是一种正确的方法。 谢谢。我所说的代码是指 Entityframework entityframeworktutorial.net/code-first/… 引入的 Code First 方法以上是关于我应该使用外键吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章