我对数据库设计有一些疑问.
这有名字吗?
这是好习惯吗?
任何性能考虑?
我有一个用于存储关系的通用表结构.
最近我重构了一些使用这种通用结构而不是直接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运行太慢的连接问题.看起来你在这个表中添加的查询速度越慢.
您应该始终使用"普通"FOREIGN KEY强制执行参照完整性.
简而言之,FOREIGN KEYs具有以下优点:
它们已经在DBMS中实现.
它们是陈述性的,自我记录的和"显而易见的".
它们不能被绕过(除非明确禁用或删除).
他们是对的.
他们很快.
它们支持级联引用操作(例如ON DELETE CASCADE).
DBMS知道数据是相关的,允许它在某些情况下找到更好的查询计划.
如果您使用的是ORM工具,它可以自动生成对象之间的引用.
以下是在应用程序代码中强制引用完整性的相应缺点:
您正在复制已完成的工作.
这是必要的,可能"深埋"在您的应用程序源代码中,并且更难维护.
具有错误的单个客户端应用程序可能会破坏参照完整性(并破坏数据).
您可能在应用程序代码中错误地实现了它们.它从一开始看起来很简单,但在并发环境中,很容易引入竞争条件.
即使您已正确实现它们,您也可能使用某种形式的锁定来避免竞争条件,这可能比DBMS中内置的特别优化的FK更慢/更低可伸缩性.
你必须自己实现级联.
DBMS不知道数据是否相关,这可能产生次优查询计划.
您可能需要在您选择的ORM工具中进行更多手动操作.
这有名字吗?
从来没听说过.我听说过使用"通用FK"这个术语,但这可能并不普遍.
这是好习惯吗?
不(见上文).
任何性能考虑?
是的(见上文).