移除外键约束,参照完整性和Hibernate

3
我的同事提到我们的客户DBA建议将所有外键约束从我们项目的Oracle DB架构中移除。最初我不同意这个决定,因为我是开发人员而不是DBA。后来我意识到这个决定可能有一些理由。因此,我正在尝试获取这个决定的利弊。
项目信息:
1. 使用Hibernate持久化的Spring应用程序。 2. Oracle 10g DB 3. 有批处理作业仅使用SQL-loader或纯JDBC。
以下是我列出的优缺点(如果我错了,请纠正我)
优点:
1. 由于应用程序持久性由Hibernate管理,因此外键级联不是必需的。它由具有适当级联选项的Hibernate进行管理。 2. Hibernate DELETE操作(包括删除级联选项)在删除其主键记录之前删除外键表记录(即避免引用完整性问题)。对于没有外键的情况、有外键的情况和有级联外键的情况,这种行为都是相同的。但是添加外键会不必要地减慢Oracle删除操作。
缺点:
1. Hibernate提供了管理对象之间关联和级联操作的机制,但从未提供DB所需的完整引用完整性解决方案。 2. 那些仅使用SQL-loader或纯JDBC的批处理作业需要引用完整性。
各位,请给我建议。如果你们中有任何一位是DBA,请提供DBA的理由。
谢谢。

2
你的客户数据库管理员是个白痴,应该被解雇或者晋升为经理 ;-) - Tony Andrews
4个回答

9
我以前从未听过DBA提出这样的建议!应用程序开发人员可能会,但从未听过Database Administrator这么说。这太不可思议了。
Tom Kyte多次表示(例如here):应用程序会来去,但数据是永恒的。
根据我的经验,我曾经使用过20多年的Oracle数据库。它们最初是在Oracle 6中创建的,并在多年内迁移到10G或11g - 相同的数据。但是顶部的应用程序呢?首先是Forms 3.0,然后在某些情况下它们被迁移到C ++,在一些情况下重建为Forms 6i,在一些情况下重建为Application Express。当然,ADF也是一个可能性;又或者采用SOA架构......
当前的应用程序开发工具有什么特别之处,以至于它突然接管了Oracle作为DBMS的工作?

3
如果在应用程序层实现FK功能,当下一个新的光鲜亮丽的工具/框架出现时,您将不得不重新实现它。 - dpbradley
1
每个经验不足的开发者都想打破关系模型,因为在过去40年里,数十亿人工时开发的数百万个数据库肯定充满了错误、不足和残留结构。我的“应用程序”、“中间层”、“资源文件”、“数据访问层”、“贵宾犬”肯定可以更“高效”、“有用”、“响应快”,在“约束执行”、“引用完整性”、“索引”、“分组”等方面。 - Stephanie Page

6

我曾经在一些决定放弃参照完整性约束的项目中处理过数据库。

我们不得不编写“QC script”来检测每个表关系的孤立行(外键约束可以防止孤立行的出现)。

当然,一旦发生了这种情况,我们就需要有解决孤立行的策略。包括以下几种选择:

  • 删除孤立行。
  • 归档孤立行。
  • 将任何孤立的外键值更新为NULL。
  • 将任何孤立的外键值更新为父表中某个现有值。
  • 接受这些异常数据,编写更多代码从报告中排除这些孤立行。或许可以使用所有表格的视图?

您可能需要安排一个每周定期与该数据库利益相关者开会,以审查QC脚本报告,并决定如何处理每个孤立行。

没有任何框架可以像运行在数据库中的约束那样可靠地执行参照完整性。只有数据库可以提供真正的原子变化并确保一致性。


那么,你为所有这些工作换来了什么优势? - Stephanie Page
@Stephanie Page:我的故事想要表达的是,放弃RI约束会导致太多的工作量。正确使用外键约束可以防止许多类型的异常情况,并减少你的工作量。 - Bill Karwin
我知道你的工作,所以我认为那就是你的意思...但它看起来几乎像一份如何做的食谱,而不是反对它的警告。对我们来说,做这么多工作似乎很愚蠢,但是有些人非常反对RI,你刚刚给了他们一个项目计划。所以我扮演了老实人...“哎呀,比尔,这真的值得吗?” - Stephanie Page
@Stephanie Page:啊哈,这只是表明在纯文本的媒介中很难传达讽刺意味。无论如何,原帖作者似乎明白这个轶事说明为什么不值得这样做。 - Bill Karwin

4

由于数据库约束得到保证,因此在某些情况下,它们可以允许额外的优化。

例如,假设您有一个视图

CREATE VIEW orders_vw AS
SELECT ord.order_id, ord.customer_id, lin.product_id
FROM orders ord JOIN order_lines lin on ord.order_id = lin.order_id

如果您有一个查询,执行SELECT product_id FROM orders_vw WHERE order_id = :val 通过强制完整性,数据库知道order_lines中的任何order_id都有父表中的一行,由于orders表中没有选择任何值,因此它可以通过不访问orders表来节省工作量。 如果没有约束条件,数据库无法确定order_lines中的条目是否有父项,因此必须额外访问orders表以进行检查。

根据您的查询模式,您可能会发现删除约束实际上会增加数据库的工作负载。


+1,但这并不完全正确。一些数据库允许您创建约束,这些约束不受DB强制执行,但可以被优化器使用。在Oracle中,它们称为“信任”约束,并使用RELY关键字。 - Stephanie Page

-2
通常情况下,外键的删除是数据库性能优化的起点。这是一种权衡:您在DBMS级别上出售保证完整性并必须自行管理它(使用Hibernate相当容易但需要在纯SQL中非常准确),而且由于查询中的外键检查相当昂贵,因此可以获得增加的查询性能。

-1 表示“由于查询中的外键检查非常耗费资源,因此您可以获得更高的查询性能。” - Rob van Wijk
4
不,你不需要:外键约束对查询没有任何成本,只会影响插入、更新和删除操作。 - Tony Andrews
2
@Tony:我同意,但我也发现对于某些人(和某些DBMS),所有的DML语句都被称为查询,并且有四种类型:选择查询、插入查询、更新查询和删除查询。 - AndyDan

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