【问题标题】:Question about data design, circular foreign keys关于数据设计,循环外键的问题
【发布时间】:2011-08-17 01:42:29
【问题描述】:

我稍微简化了这一点,但我们在一个大型成熟 .net 项目使用的大型现有 sql2008 数据库中有一个 User 表和一个 TestResult 表。为用户提供了许多测试,并且这些测试被大量访问,因此为了加快速度,User 表包含一个 CurrentTestResult 和一个 PendingTestResult 分别用于最后一个测试和一个正在进行的测试。此外,您不能只查看日期来查找当前测试,因为有时测试可能会失效,与未决测试相同。

TestResult 当然包含一个外键 UserID 和 User 有 2 个外键指向 TestResult。这种方式已经很久了,没有太大的问题。有时,即使不是他们的测试,测试也会以某种方式固定给用户,因此显然它并不完美,无论如何我都需要追查这个漏洞。

我们正在转向一个断开连接的模型,他们告诉我我们必须删除所有循环键。他们不想暂时删除并重新添加密钥,因为如果该过程失败,他们将不知道该怎么办。不熟悉这个过程我不确定这是否有意义,但在我弄清楚我修复引用的缺点之后,这是一个问题。

我可以为我看到这个问题的几个解决方案,所有这些都有其缺点。

A) 其中最简单的就是删除 2 个外键。我对此没有什么大问题,因为 FK 约束只是图片的一半,除非它链接到正确的用户,否则它仍然无效。我必须权衡保留密钥的风险与代码更改。

B) 我可以添加一个交叉引用表来保存当前和待定的链接。我认为这将为我提供与现在基本相同的保护,只有轻微的性能差异。我认为循环键问题消失了,因为他们可以最后插入外部参照。我将进行大量代码更改。

C) 我可以向 TestResults 添加 2 列并标记当前和待处理的记录。这里的问题是现在我必须确保每个用户只设置 1 个标志,并且现在每次访问我的数据时都必须进行索引查找。所以我失去了保护和性能,我仍然有大量的代码更改。

D)?

我确定这是一个相当普遍的模式,有没有“正确”的解决方案?

【问题讨论】:

  • 有没有最好的解决方案,有没有更好的解决方案。

标签: sql-server database-design foreign-keys


【解决方案1】:

您的结构对我来说不是很清楚,但您可以将部分或全部更改隐藏在可更新视图后面。

我感觉选项 B 将是您的最佳选择。你基本上是在谈论这样的桌子,对吧? (航空代码)

create table xref (
    user_id integer not null references users (user_id),
    current_test_result whatever not null references tests (test_id),
    pending_test_result whatever references tests (test_id),
    primary key (Hmmmmm)
);

待处理的测试结果必须可以为空吗?我想这无关紧要——如果它必须可以为空,那么它必须在现有表中已经可以为空。

【讨论】:

  • 我实际上在想 USERID、TestResultID、TestTypeID。至少我还有另一个选择可以考虑。而且我没有考虑过可更新的视图。
  • 可更新视图是 SQL 数据库实现逻辑数据独立性的方式。构建它们有点麻烦,但它们真的很有用。
【解决方案2】:

您确定选项 A 实际上会成为性能问题吗?如果您的测试表上有一个包含用户 FK 的索引,然后按时间顺序降序排列 - IDENTITY 列或测试时间戳,那么当您从 user_id = X 的 TEST 表中选择 TOP 2 时,此索引将非常有用. 你不必担心你的循环外键会出错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 2011-06-24
    • 2021-07-03
    相关资源
    最近更新 更多