【问题标题】:Removal of foreign key constraints, Referential integrity and Hibernate去除外键约束、参照完整性和休眠
【发布时间】:2011-03-13 17:40:24
【问题描述】:

我的同事提到我们的客户 DBA 建议删除我们项目 Oracle DB 模式中的所有外键约束。起初我不同意这个决定。我是开发人员而不是 DBA。所以后来意识到这个决定背后可能有一些原因。所以我正在尝试了解这个决定的利弊。

项目信息:

  1. 具有 Hibernate 持久性的 Spring 应用程序。
  2. Oracle 10g 数据库
  3. 有些批处理作业仅使用 SQL-loader 或普通 JDBC。

这是我的优缺点列表(如果我错了,请纠正我)

优点:

  1. 由于应用程序持久化由 Hibernate 管理,因此不需要外键级联。它由 Hibernate 使用适当的级联选项进行管理。

  2. Hibernate DELETE 操作(包括删除级联选项)在删除其主键记录之前删除外键表记录(即避免引用完整性问题)。对于无外键情况、外键情况和外键级联情况,此行为相同。但是添加外键会不必要地减慢 Oracle 删除操作。

缺点

  1. Hibernate 提供了一种机制来管理对象之间的关联以及关联中的级联操作。但它从来没有像 DB 那样提供完整的参照完整性解决方案。

  2. 那些仅使用 SQL 加载器或普通 JDBC 的批处理作业需要参照完整性。

伙计们,我需要你的建议。如果你们中的任何人是 DBA,请提供 DBA 的附加理由。

谢谢。

【问题讨论】:

  • 你的客户 DBA 是个白痴,应该被解雇,或者可能被提升为经理 ;-)

标签: oracle hibernate referential-integrity


【解决方案1】:

我以前从未从 DBA 那里听到过这样的建议!来自应用程序开发人员,是的,但绝不来自数据库管理员。它乞求信仰。

Tom Kyte 曾多次说过(例如here):应用程序来来去去,但数据是永恒的。

根据我自己的经验,我从事过 20 多年的 Oracle 数据库工作。他们从 Oracle 6 开始,多年来一直迁移到 10G 或 11g - 相同的数据。但是最重​​要的应用程序呢?首先它们是 Forms 3.0,然后在某些情况下迁移到 C++,在某些情况下在 Forms 6i 中重新构建,在某些情况下在 Application Express 中重新构建。 ADF 当然是另一种可能性。或者也许是 SOA 架构...

当前的应用程序开发工具有什么特别之处,它突然接管了 Oracle 作为 DBMS 的工作?

【讨论】:

  • +1 在应用层实现 FK 功能,当下一个新的、闪亮的工具/框架出现时,您将可以从头开始。
  • 每个缺乏经验的开发人员都想打破关系模型,因为过去 40 年开发数百万个数据库的数十亿工时的工作肯定充满了错误和错误、大量的低效率和残留结构体。我的“应用程序”、“中间层”、“res 文件”、“数据访问层”、“贵宾犬”当然可以更“高效”、“有用”、“响应”在“约束执行”、“参照完整性”、 “索引”、“分组”等
【解决方案2】:

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

我们必须编写“QC 脚本”来检测与每个表关系相关的孤立行(孤立行会被外键约束阻止)。

然后当(不是如果)它们发生时,我们必须制定解决孤儿问题的策略。选择包括以下内容:

  • 删除孤立行。
  • 归档孤立的行。
  • 将所有孤立的外键值更新为 NULL。
  • 将任何孤立的外键值更新为父表中的某个现有值。
  • 忍受异常。编写更多代码以从报告中排除孤儿。可能是所有表的一组 VIEW?

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

没有任何框架可以像在数据库中运行的约束那样可靠地强制引用完整性。只有数据库才能提供真正的原子更改并确保一致性。

【讨论】:

  • 那么你从所有这些工作中获得了什么好处?
  • @Stephanie Page:我的故事的重点是放弃 RI 约束会导致工作量太大。正确使用外键约束可以防止许多类型的异常并减少您的工作。
  • 我知道你的工作,所以我认为这就是你的意思......但它看起来几乎就像是如何做到这一点的秘诀,而不是反对它的警告。对我和你来说,做所有这些工作看起来很愚蠢,但是有些人对 RI 如此死心塌地,你刚刚给了他们一个项目计划。所以我在扮演直男……“哎呀,比尔,值得吗?”
  • @Stephanie Page:啊哈,这表明在纯文本媒体中很难传达讽刺意味。无论如何,OP 似乎明白这个轶事说明了为什么它值得。
【解决方案3】:

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

例如,假设您有一个视图

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 但这并不完全正确。某些数据库允许您创建数据库不强制执行但可以由优化器使用的约束。在 Oracle 中,它们被称为“信念”约束并使用 RELY 关键字。
【解决方案4】:

通常,外键删除是数据库性能优化的开始。这是一种权衡:您在 DBMS 级别上出售有保证的完整性,并且必须自己管理它(这在 Hibernate 中相当容易,但在普通 SQL 中需要非常准确),并且由于查询中的外键检查,您可以获得更高的查询性能相当昂贵。

【讨论】:

  • -1 表示“您可以提高查询性能,因为查询中的外键检查非常昂贵”。
  • -1 不,你不需要:外键约束在查询中没有任何成本,仅在插入、更新和删除中。
  • @Tony:我同意,但我也发现对于某些人(以及某些 DBMS),所有 DML 语句都称为查询,并且有 4 种类型:选择查询、插入查询、更新查询和删除查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多