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

时间:2010-07-09 07:09:56

标签: oracle hibernate referential-integrity

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

项目信息:

  1. 使用Hibernate持久化的Spring应用程序。
  2. Oracle 10g DB
  3. 批处理作业只使用SQL-loader或普通JDBC。
  4. 这是我的利弊清单(如果我错了请纠正我)

    优点:

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

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

    3. 缺点

      1. Hibernate提供了一种机制,用于管理对象之间的关联以及关联中的级联操作。但它永远不会提供DB所具有的完整的参照完整性解决方案。

      2. 这些批处理作业只需使用SQL-loader或普通JDBC,就需要参照完整性。

      3. 伙计们,我需要你的建议。如果你们中的任何人都是DBA,请提供DBA方面的原因。

        谢谢。

4 个答案:

答案 0 :(得分:9)

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

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

根据我自己的经验,我参与了20多年前的Oracle数据库。他们从Oracle 6开始,多年来迁移到10G或11g - 相同的数据。但坐在上面的应用程序?首先它们是Forms 3.0,然后在某些情况下,它们被迁移到C ++,有些已经在Forms 6i中重新构建,在Application Express中重建了一些。 ADF当然是另一种可能性;或者可能是SOA架构......

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

答案 1 :(得分:6)

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

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

然后,当他们(而不是)他们出现时,我们必须制定如何解决孤儿的政策。选择包括以下内容:

  • 删除孤立的行。
  • 归档孤立行。
  • 将所有孤立的外键值更新为NULL。
  • 将所有孤立的外键值更新为父表中的某个现有值。
  • 与异常生活在一起。编写更多代码以从报告中排除孤儿。可能在所有表格上都有一组VIEW?

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

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

答案 2 :(得分: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表的额外工作以进行检查。

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

答案 3 :(得分:-2)

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