Sql - 间接外键

时间:2013-12-30 15:47:10

标签: database-design foreign-keys relational-database

我对数据库设计有一些疑问。

  1. 这是否有名字?
  2. 这是好习惯吗?
  3. 任何性能方面的考虑?
  4. 我有一个用于存储关系的通用表结构。

    最近我重构了一些使用这种通用结构而不是直接Fk列的东西,但现在我不确定这是不是最好的主意。

    原始架构:

    
     +------------------+       +---------------------+    +----------------------+
     | Book             |       | Note                |    | MetaParent           |
     |------------------|       |---------------------|    |----------------------|
     | Id               |       | Id                  |    | Id                   |
     | NoteId           |       | MetaParentId:(Null) |    | MetaTableId          |
     |                  +-------+                     +----+ KeyValue             |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     +------------------+       +---------------------+    +----------------------+

    新架构

    
     +------------------+       +---------------------+    +----------------------+
     | Book             |       | Note                |    | MetaParent           |
     |------------------|       |---------------------|    |----------------------|
     | Id               |       | Id                  |    | Id                   |
     |                  |       | MetaParentId:(Null) |    | MetaTableId          |
     |                  +       +                     +----+ KeyValue             |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     |                  |       |                     |    |                      |
     +------------------+       +---------------------+    +----------------------+

    因此,基本上不是在Book和Note之间建立直接的Fk关系,而是使用MetaTableId / KeyValue列通过MetaParent表建立间接关系。

    目前,MetaParent表有大约500k条记录,而且事情正在以可接受的方式运行。但是我们每晚都在重建索引。

    我担心的是,现在Book和Note之间的关系并不明显。您必须知道一个存在并使用MetaParent表。

    同样表现,我不确定在什么时候我们遇到了针对MetaTableId / KeyValue运行太慢的连接问题。看起来你在这个表中添加的查询速度越慢。

1 个答案:

答案 0 :(得分:10)

您应该始终使用“普通”FOREIGN KEY强制执行参照完整性。

简而言之,FOREIGN KEYs具有以下优势:

  1. 它们已经在DBMS中实现。
  2. 他们是声明性,自我记录和“明显”。
  3. 无法绕过它们(除非明确禁用或删除)。
  4. 他们是对的。
  5. 他们很快。
  6. 他们支持级联引用操作(例如ON DELETE CASCADE)。
  7. DBMS知道数据是相关的,允许它在some cases中找到更好的查询计划。
  8. 如果您使用的是ORM工具,它可以自动生成对象之间的引用。
  9. 以下是在应用程序代码中强制引用完整性的相应缺点:

    1. 您正在复制已经完成的工作。
    2. 这是命令式,可能“深埋”在您的应用程序源代码中,并且难以维护。
    3. 具有错误的单个客户端应用程序可能会破坏参照完整性(并破坏数据)。
    4. 您可能在应用程序代码中错误地实现了它们。它从一开始看起来很简单,但在并发环境中,it is easy to introduce race conditions
    5. 即使您已正确实现它们,您也可能使用某种形式的锁定来避免竞争条件,这可能比DBMS中内置的特别优化的FK更慢/更低的可扩展性。
    6. 你必须自己实施级联。
    7. DBMS不知道数据是否相关,这可能会产生次优的查询计划。
    8. 您可能需要在自己选择的ORM工具中进行更多手动操作。

    9.   

      这有名字吗?

      不是我知道的。我听说过使用“通用FK”这个术语,但这可能并不普遍。

        

      这是好的做法吗?

      否(见上文)。

        

      任何性能考虑因素?

      是(见上文)。