Sql - 间接外键

And*_*ers 3 database-design foreign-keys relational-database

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

  1. 这有名字吗?
  2. 这是好习惯吗?
  3. 任何性能考虑?

我有一个用于存储关系的通用表结构.

最近我重构了一些使用这种通用结构而不是直接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运行太慢的连接问题.看起来你在这个表中添加的查询速度越慢.

Bra*_*vic 11

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

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

  1. 它们已经在DBMS中实现.
  2. 它们是陈述性的,自我记录的和"显而易见的".
  3. 它们不能被绕过(除非明确禁用或删除).
  4. 他们是对的.
  5. 他们很快.
  6. 它们支持级联引用操作(例如ON DELETE CASCADE).
  7. DBMS知道数据是相关的,允许它在某些情况下找到更好的查询计划.
  8. 如果您使用的是ORM工具,它可以自动生成对象之间的引用.

以下是在应用程序代码中强制引用完整性的相应缺点:

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

这有名字吗?

从来没听说过.我听说过使用"通用FK"这个术语,但这可能并不普遍.

这是好习惯吗?

不(见上文).

任何性能考虑?

是的(见上文).

  • 这种模式的一个名称是[内部平台效应](http://en.wikipedia.org/wiki/Inner-platform_effect) - 即实现一个可自定义的系统,使其成为软件平台的糟糕复制品用来实现它. (4认同)