我一开始故意把这个模糊不清。我正在寻找讨论,哪些问题比我正在寻找难的答案更重要。
我正在设计一个类似投资组合管理的应用程序。我到目前为止的设计是
我的问题是关于这些事情的时间性质。出现问题,然后褪色。解决方案具有预期的解决方案日期,但可能会在开发时进行修改。随着问题和解决方案的发展,关系的程度可能会随着时间而变化。
所以,问题是:对这些东西进行版本控制的最佳设计是什么,这样我就可以获得我的投资组合的当前和历史视角?
后来:也许我应该把它作为一个更具体的问题,尽管@Eric Beard的答案值得一试。
我考虑了三种数据库设计。我足以证明他们的缺点。我的问题是:选哪个,或者你能想出更好的东西吗?
table problems
int id | string name | text description | datetime created_at | int previous_version_id
foreign key previous_version_id -> problems.id
这是有问题的,因为每次我想要新版本时,我都必须复制整行,包括那个长description
列。
table problems
int id | string name | text description | datetime created_at
这只是将Problems和Solutions表中的关系移动到Relationships表中。同样的重复问题,但也许有点“清洁”,因为我已经有了一个抽象的关系概念。
table problems
int id
table attributes
int id | int thing_id | string thing_type | string name | string value | datetime created_at | int previous_version_id
foreign key (thing_id, thing_type) -> problems.id or solutions.id
foreign key previous_version_id -> attributes.id
这意味着要加载问题或解决方案的当前版本,我必须获取属性的所有版本,按日期对它们进行排序,然后使用最新版本。那可能并不可怕。对我来说真正糟糕的是我无法在数据库中键入 - 检查这些属性。 value
列必须是自由文本。我可以将name
列引用到具有attribute_names
列的单独type
表中,但不会强制 { {1}}表。
后来仍然:回应@Eric Beard关于多表外键的评论:
唉,我所描述的是简单化的:只有两种类型的东西(问题和解决方案)。我实际上有大约9或10种不同类型的东西,所以我的策略下有9或10列外键。我想使用单表继承,但事情几乎没有什么共同之处,将它们组合到一个表中是非常浪费。
答案 0 :(得分:1)
就数据库设计而言,版本系统类似于SVN,你实际上从未进行任何更新,只需在事情发生变化时插入(带有版本号),可能就是你所需要的。这称为MVCC,多值并发控制。维基是另一个很好的例子。
答案 1 :(得分:1)
@Gaius
foreign key (thing_id, thing_type) -> problems.id or solutions.id
小心这些“多向”外键。我的经验表明,当你的连接条件必须在确定要加入哪个表之前检查类型时,查询性能会受到严重影响。它似乎不是优雅但可以为空的
problem_id and solution_id
会更好。
当然,当您必须添加检查以获取最新版本的记录时,查询性能也会受到MVCC设计的影响。权衡是你永远不必担心与更新争用。
答案 2 :(得分:1)
您如何看待这个:
表问题表格问题
int revision | int id |字符串名称|文字说明| datetime created_at
外键id - > problems.id
在更新之前,您必须在修订表中执行其他插入。这个额外的插入很快,但是,这是你需要支付的费用
答案 3 :(得分:0)
我想有
将常见Thing属性移动到单继承表中,然后添加custom_attributes
表。这使得外键更简单,减少重复,并允许灵活性。它没有解决附加属性的类型安全问题。它还增加了一点复杂性,因为Thing现在有两种方法可以拥有一个属性。
如果description
和其他大字段保留在Things表中,它也无法解决重复空间问题。
table things
int id | int type | string name | text description | datetime created_at | other common fields...
foreign key type -> thing_types.id
table custom_attributes
int id | int thing_id | string name | string value
foreign key thing_id -> things.id
答案 4 :(得分:0)
选择一个数据结构是个好主意,这个数据结构可以让你对模型提出的常见问题很容易回答。你最有可能在大多数时候对目前的职位感兴趣。有时,您需要深入了解特定问题和解决方案的历史记录。
我会为表示当前位置的问题,解决方案和关系提供表格。还会有一个problem_history
,solution_history
等表格。这些是问题的子表,但也包含VersionNumber
和EffectiveDate
的额外列。关键是(ProblemId
,VersionNumber
)。
更新问题时,您可以将旧值写入problem_history
表。因此,您可以选择时间点查询,因为您可以选择在特定日期有效的problem_history
记录。
之前我已经完成了这项工作,我还创建了一个UNION problem
和problem_history
的视图,因为这在各种查询中有时很有用。
选项1使查询当前情况变得困难,因为所有历史数据都与您当前的数据混合在一起。
选项3对于查询性能会很糟糕,而且对于代码来说是讨厌的,因为您将访问许多行,这应该只是一个简单的查询。