Lee*_*ren 1 rdbms foreign-key database-design best-practices
根据我们组织的一些数据库管理员的说法,通常不建议在我们的 MySQL 数据库中实际强制执行外键关系。相反,最好用伪外键 ID 列简单地表示它,并为外键强制执行额外的应用程序处理。原因是随着数据库的扩展,插入和删除(尤其是级联的)变得非常昂贵。
但这不是违背了 RBDMS 的初衷吗?据我了解,似乎使用 RBDMS 开始的最大原因之一(除了强制 ACID 属性)是确保最小化涉及相关(即通过 FK 由连接表绑定)对象的应用程序查询处理。
那么使用伪外键和附加应用程序处理通常更实用吗?而且,如果是这样,您为什么还要使用 RBDMS?我认为原因是应用程序处理仍然比 NoSQL 解决方案略少(而且更直接)?
TL;博士。除非您有一个引人注目的小众案例, 否则请充分利用您的 RDBMS 的功能!
嗯……你说:
我们组织的一些数据库管理员
其他人怎么说?
你还写:
最好用伪外键 ID 列简单地表示它
究竟什么是“伪外键 ID 列”?
在整点(和最大的好处)您使用获得FOREIGN KEY
S(FK
S)是你有自动执行的Declarative Referential Integrity
(DRI
) -见下文。数据库系统的这种功能在更改数据时故意不灵活。这是为了您的开发人员的利益、您的 DBA 的利益、您公司的利益,最重要的是,为了您的客户的利益!
现代RDBMS(其中大部分反正)是一个复杂的编程环境,在自己的权利,你可以利用,以保持最大程度的控制的数据尽可能接近到您的数据。
您可以有效地对数据旁边的数据进行细粒度控制,这是最好的位置。您的数据库是防御流氓应用程序(大部分是诚实的错误)和/或 DBA/系统管理员(同样,大部分是诚实的)以导致数据不一致的方式修改数据的最后堡垒。
不一致的数据可能比无用更糟糕 - 如果您知道数据已损坏,则可以从备份中恢复,但如果不一致,则可能会根据错误的前提做出关键任务决策!
您的 DBA 说:
随着数据库的扩展,插入和删除(尤其是级联的)变得非常昂贵
然而,您似乎正在使用pseudo foreign-key ID columns
? 这增加了它自己的成本 - 例如,对于INSERT
进入子表,您必须(在应用程序中 - 并且所有在一个事务中)查询数据库(大概检查父母的存在?)然后执行您的(一致)INSERT
然后COMMIT
?
对于父级DELETE
和/或UPDATE
父级,您必须根据规则(ing)检查子级,然后DELETE
或UPDATE
子级的存在,然后在一个事务中检查/父级。在数据库中设置 DRI 可以消除所有这些开销!请参阅此处和该线程的其余部分。CASCAD
DELETE
UPDATE
在我看来,数据丢失、孤儿记录、无子女的父母以及来自愤怒客户的深夜来电威胁要拔掉您公司及其软件的插头,这将变得更加昂贵!
是的,执行 DRI 需要付出一定的代价。你的数据库管理员都建议你在应用程序执行本-然而,这是也是昂贵和它的远更昂贵,远远更容易出错,而且远远耗费更多的时间来做到这一点的应用程序是不是比你使用它的RDBMS(见上面的例子)。
最年轻的主流 RDBMS 产品 MySQL 于23 年前首次发布,它只是作为 Oracle(1979 年)、Ingres(80 年代中期或更早- 在当时很重要)等系统的轻量级副本, Sybase/MS SQL Server(1984 年)、PostgreSQL(也是 80 年代中期或更早)和 Interbase/Firebird(1984 年- 在当时也很重要)。
因此,这些系统比您的应用程序存在的时间要长得多。
您的 DBA 所提议的是重新发明轮子 - 一个轮子每天对世界各地的银行、超市、工厂、办公室和仓库(非详尽列表)的数百万用户都非常有效。
这里有几个主要问题。
谁知道?也许您拥有一支优秀的热门程序员团队,可以在不到 3 年的时间内实现主流 RDBMS 功能?呃……我为什么不买那个剧本?嗯,上面两个开源系统中“最便宜的”(但到目前为止更好的恕我直言) - PostgreSQL -花费 1500 万美元和 269 个工作年,而 MySQL 花费6350 万美元和 1155 个工作年。你认为你的团队能做到吗?
你有你的数据库软件——通过试图规避/重写它的 DRI 功能,你实际上是在浪费他们多年的编程工作和测试以及他们(字面上)数百万最终用户的(有效)测试。
假设,在一个阳光明媚的早晨,您的老板/客户/税务机关/决定您需要编写新应用程序来使用您的数据库的任何人?你必须实现所有的DRI的从头再来!并且可能使用不同的语言,因为你的老板在一些机上杂志上读到X 是最常用的语言。它就会像déjà vu
遇到Groundhog Day
一遍!
然后,您聘请了一个合同天才程序员,他用 X 为他的本科论文编写了一个系统。他不知道 table_W 中的 column_A 是 table_Z 中 column_B 的子项,因此他每天愉快地生成数百行代码,这些代码可以在您的测试数据上流畅而快速地运行。
然后它落在客户身上,他们开始注意到记录正在丢失 - 总和/记录计数不正确。您的承包商已转移到一家初创公司 ( Cowboys 'R Us
),而您只能抱着孩子!(这种情况也可能会出现在您当前的设置中)。
看看这三篇文章
我不是说NoSQL系统没有一个“小众”,这只是一个利基是正是他们什么也有(多,在同样的上面)。除非您有与 NoSQL 用例明确一致的非常具体的需求,否则最好避免它们(恕我直言)。
如果以上内容不能说服您,请考虑以下最后几点:
更多战争故事,给第 8 章的粉丝!“现在准备好阅读有关‘世界上最糟糕的甲骨文项目’的所有内容。” - 乔纳森·刘易斯。
本章介绍了开发 Oracle 数据库应用程序时最常见的一些错误。您肯定会认出其中一些,因为有太多人固执地坚持某些信念。我知道当我遇到这样的常见论点时,我喜欢提出他的几个观点:
- 我们希望我们的应用程序是“独立于数据库的”。
- 我们将在应用程序级别检查数据完整性,而不是利用 Oracle 的约束检查能力。
注意- 第 2 点。 - 这正是您打算做的!
看看Brian Aker在这里关于 NoSQL 的有趣谈话——他指出 NoSQL 可以用于处理陈旧数据的临时查询,只是 SQL 也很擅长对数据进行切片和切块。
SQL的主要优点是您不必编写新的 Map-Reduce 作业或其他任何东西来分析您的数据,您只需编写一个查询,等等,您就完成了!如果您没有FOREIGN KEY
在 RDBMS 中使用s,那么您实际上处于 SQL 和 NoSQL 之间的中间地带!
有关于 FK 是不必要的开销的老太婆故事。由于(出于好的原因,但现在可能是遗留的,特别是空间的原因),某些 RDBMS 没有/不会自动在外键字段上创建索引(在大多数情况下应该这样做),这一概念仍然存在。这导致了错误的观点,即外键是没有好处的开销,这对于大量用例而言并非如此!
你说:
如果是这样,您为什么还要使用 RBDMS?
这个问题问得好。如果您没有将 RDBMS 用作 RDBMS,那么为什么要使用它呢?只需将数据放入 Notepad/vi 即可!
您应该与管理层认真地坐下来解释为什么使用 RDBMS 的功能是一个好主意。此外,我会要求您的 (No- FK
) 人证明不使用FOREIGN KEY
s是合理的。除非您的公司有一个真正且紧迫的 NoSQL 利基市场,否则请向他们指出 Micheal Stonebraker 和/或 Jonathan Lewis 在这方面的工作。
最后,我给你的建议,如果你的公司/管理层坚持追求这种疯狂,那就是跑得非常远,非常非常快!你最终会陷入这样的境地:你不断地救火,在 03:30 从床上醒来,更糟糕的是,你将没有机会提高你的技能或学习任何有价值的东西。