MySQL - 在Web应用中使用外键是否有用/可行?

4
我遇到了有关FK和Web应用程序的讨论。基本上,一些人说,Web应用程序中的FK并没有真正的改进,并且在某些情况下甚至会使应用程序变慢。
你们认为呢?你们有什么经验?
编辑:请注意,我知道FK的作用和目标,我只是不确定它们是否会对像YouTube这样的Web应用程序的性能产生显着负面影响。
以下是InnoDB引擎的创建者,Innobase公司的创始人兼首席执行官Heikki Tuuri的一句话:
“在更新行时,InnoDB立即检查外键约束,不进行批处理或将检查延迟到事务提交。外键约束通常会对性能产生严重的开销,但有助于维护数据一致性。外键会增加行级锁定量,并可能使其传播到除直接更新的表之外的许多表。”

请注意,要获取(工作)Forn键(正如Granny Weatherwax所说),您需要使用支持它们的表类型,通常是InnoDB - Powerlord
8个回答

14
"外键将确保一个表中的一行,具有一个字段order_id引用了orders表的一个order_details表,永远不会有一个不存在于orders表中的order_id值。

在关系型数据库中,外键并非必须,但它们绝对是避免破碎的关系和孤立行(即参照完整性)所必需的。在数据库层面上强制执行参照完整性是要求ACID中的C元素存在的。

至于你对性能的担忧,通常情况下,如果有的话,性能影响将是微不足道的。我建议在所有外键约束都放置好后,只有在您无法通过其他方式解决真正的性能问题时才进行实验。

此外,作为一个侧记,虽然与MySQL没有直接关系,但这是来自Microsoft Patterns and Practices: Chapter 14 Improving SQL Server Performance的引用:

当主键和外键在数据库模式中定义为约束时,服务器可以使用该信息创建最佳执行计划。

"

9

保留您的外键-这可以确保无论谁为您编写代码,您的数据都保持在可用和预期的格式中。除非您面临严重的高流量问题,否则我甚至不会考虑删除它们。


5

网络应用程序与其他任何类型的应用程序没有区别。当然,你可能会因省略数据完整性检查而获得微小的加速,但这不会太明显,而且代价太高。

如果没有引用完整性,一旦出现悬空的外键(由于某些没有经过适当测试的代码路径或部分更新失败),很多查询都会失效,因为它们依赖于该键指向某个对象。这种情况非常常见,直到你深入数据库并手动删除悬空引用之前,整个网站都会崩溃。

(*:除非你正在使用事务。但让我们面对现实吧,如果你是那种不使用引用完整性的作者,你也不太可能使用事务。)


5
除了这里提到的所有好处之外(实际上没有不使用它们的理由),还有另一个很好的理由:
外键可以记录您的数据模型,使人们更容易理解它(这类似于cdonner提到的优点)。

没错,我一直都是用它们来处理这个问题的。 - yoda
+1 这是一个如此显而易见的原因!干得好!任何参与过由他人设计的数据库项目的人都会理解这一点。 - bunn_online

3
在未来,你的应用程序数据库中可能会有其他软件操作数据。例如:
  • 从第三方系统批量导入数据
  • 无法实时处理的批处理
  • 等等
通过使用外键,你将确保数据库的完整性得到维护,因为任何违反这些键的操作都会导致错误。
在我看来,性能提升(如果有的话??)不值得冒损害数据库完整性的潜在风险。

3
外键是您和数据完整性问题之间的有用障碍。它们告诉数据库代表您执行额外的工作,以确保您定义的完整性得到执行,无论某些应用程序代码出了多少岔子。这至少在每个DB程序员的职业生涯中都拯救过一次。您应该绝对将外键设计到您的模型中,特别是如果您认为您不需要它们。
也就是说,如果您正在推动数据库层的可扩展性极限,FK可能是您关闭的东西,因为理论上它们正在执行您的应用程序已经执行的重复工作(也就是说,如果没有FK,您的应用程序不应该有意地编码以破坏关系完整性的事情)。这不是懦弱者所能做的事情,而且,这并不总是性能优势(某些JOIN更有效,因为DB知道某些关系是否可以或不能有结果行)。
在所有优化方面,规则1是“不要这样做”,规则2是“不要这样做(但还没有)”。确保如果您走这条路:
1)您有具体的性能负载数据来支持您的决定
2)您可以使用开关打开或关闭它们(即不要删除它们并丢弃代码,绝对不要忽略首先设计它们)
3)您有一些能力定期验证应用程序代码是否正确执行了您设计的完整性约束(例如,每晚验证是否存在孤儿的作业)。

1

外键主要关乎完整性和功能,而非性能。如果您希望在两组列之间强制实施引用完整性,则通常使用外键是最有效和最有效的方法。如果您不需要支持这种完整性约束,则显然性能问题也不会出现。

外键可能通过支持某些类型的查询重写来提高性能,否则这些查询将无法实现。但是,这主要是一个附加好处 - 确保正在执行约束的副作用。


1

你的问题就像争论赛车不需要方向盘因为它会减速一样-毫无意义。所有的车辆都需要方向盘(至少现代的汽车是这样)。

其他人已经详细解释了外键对于数据完整性的有用性。

此外,我想指出,现代语言和框架可以使用数据库中的外键元数据来建立对象关系。Linq-to-SQL非常优雅地完成了这个任务。每当数据关系需要时,您实际上不能使用对象-关系映射框架而不定义外键。


问题不在于外键是否具有逻辑存在的意义(它们始终如此),而在于在一个大型Web应用程序中,比如YouTube,它们是否会影响整体性能。 - yoda
@Yoda,这就是为什么这个问题毫无意义。你将FK(Foreign Keys)的性能与什么进行比较?没有这些约束的同一应用程序吗?那么问题就变成了在没有它们的情况下如何更有效地实现相同的功能?这是假设您需要该功能-如果不需要,则显然该问题无关紧要。 - nvogel
这个问题涉及到在一个广泛使用的Web应用程序中,外键对性能的影响。 - yoda
Yoda,我的观点是,虽然我没有表达得很清楚,但如果外键影响性能,它们将影响所有应用程序,而不仅仅是Web应用程序。你本可以更加通用地提出问题,即“使用外键约束有什么性能影响”?这里给出了一些答案:https://dev59.com/BXRB5IYBdhLWcg3wz6QJ 正如你所看到的,普遍共识是FK将提高查询性能。 - cdonner
但我想可以争论的是,为Web应用程序提供服务的数据库看到了一些典型的数据访问模式,这些模式对于Web应用程序而言是独特的,没有其他应用程序有,所以我收回了“荒谬”的说法。 - cdonner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接