Sql – 间接外键
我有一些关于数据库devise的问题。
- 有没有这个名字?
- 这是好的做法吗?
- 任何性能考虑?
我有一个用于存储关系的通用表结构。
最近我重构了一些东西来使用这个generics结构,而不是直接的Fk列,但是现在我不确定这是否是最好的想法。
原始模式:
+ ------------------ + + --------------------- + + ------ ---------------- + | 预订| | 注意| | MetaParent | | ------------------ | | --------------------- | | ---------------------- | | Id | | Id | | Id | | 注意| | MetaParentId:(空)| | MetaTableId | | + ------- + + ---- + KeyValue | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + ------------------ + + --------------------- + + ------ ---------------- +
新的模式
+ ------------------ + + --------------------- + + ------ ---------------- + | 预订| | 注意| | MetaParent | | ------------------ | | --------------------- | | ---------------------- | | Id | | Id | | Id | | | | MetaParentId:(空)| | MetaTableId | | + + + ---- + KeyValue | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + ------------------ + + --------------------- + + ------ ---------------- +
所以,基本上,而不是Book和Note之间有一个直接的Fk关系,我们通过MetaParent表使用MetaTableId / KeyValue列build立间接关系。
目前MetaParent表有大约500k条logging,而且事情正在顺利进行。 但是我们每天晚上都会重build索引。
我的担心是,现在Book和Note之间的关系并不明显。 您必须知道存在并使用MetaParent表。
同样的performance,我不确定在什么时候我们会遇到与joinMetaTableId / KeyValue运行速度太慢的问题。 看起来你添加到这个表越慢查询会得到。
您应该始终使用“普通”FOREIGN KEY来强制引用完整性。
简而言之,FOREIGN KEY具有以下优点:
- 它们已经在DBMS中实现了。
- 他们是陈述性的 ,自我logging和“明显的”。
- 它们不能被绕过(除非明确禁用或丢弃)。
- 他们是正确的。
- 他们很快。
- 它们支持级联引用操作 (如ON DELETE CASCADE)。
- DBMS知道数据是相关的,在某些情况下允许它find更好的查询计划。
- 如果您使用的是ORM工具,它可以自动在对象之间生成引用。
以下是在应用程序代码中强制执行参照完整性的相应缺点:
- 你正在复制已经完成的工作。
- 这是必要的 ,可能“埋藏”在你的应用程序源代码中,而且难以维护。
- 有一个bug的单个客户端应用程序可能会破坏参照完整性(并损坏数据)。
- 您可能会在应用程序代码中错误地实现它们。 从一开始看起来很简单,但在并发环境中, 很容易引入竞争条件 。
- 即使您已经正确实施了它们,也可能使用了某种forms的locking来避免竞争条件,这可能会比内置于DBMS中的特别优化的FK更慢/可扩展性更差。
- 你必须实现级联自己。
- DBMS不知道数据是相关的,这可能会产生次优的查询计划。
- 您可能需要在您select的ORM工具中进行更多的手动工作。
有没有这个名字?
从来没听说过。 我听到一个术语“通用FKs”被使用,但这可能不是普遍的。
这是好的做法吗?
否(见上文)。
任何性能考虑?
是的(见上文)。