我已经做了几个项目(CMS和EC系统),需要有一些数据版本。
通常我都会带着这样的模式
+--------------+
+ foobar +
+--------------+
+ foobar_id +
+ version +
+--------------+它工作得很好,但我想知道是否有更好的方法来做它。该解决方案的主要问题在于,您必须始终使用子查询来获取最新版本。
即:
SELECT * FROM foobar WHERE foobar_id = 2 and version = (SELECT MAX(version) FROM foobar f2 WHERE f2 = 2)这使得大多数查询变得更加复杂,并具有一些性能缺陷。
因此,如果你能分享你创建版本化表的经验,以及每种方法的优缺点,那就太好了。
谢谢
发布于 2009-12-07 13:26:54
我更喜欢将历史数据放在另一个表中。我会制作foobar_history或类似的东西,并制作一个foobar_id的FK。这将使您不必同时使用子查询。这还有一个额外的好处,那就是不会用大量的历史数据污染您的主数据表,而您可能不希望在99%的时间内访问这些数据。
不过,您可能希望为更新此数据创建一个触发器,因为这需要将当前数据复制到_history中,然后进行更新。
发布于 2009-12-07 14:49:00
在我看来,最干净的解决方案是为每个需要版本化的表创建一个History表。换句话说,先有一个foobar表,然后是一个foobar_History表,在foobar上有一个触发器,该触发器会将现有数据写入到History表中,并带有时间戳和更改数据的用户。较旧的数据很容易查询,按时间戳降序排序,而且您知道主表中的数据始终是最新版本。
发布于 2009-12-07 19:24:52
我曾经在一个包含历史数据的系统上工作,我们有一个布尔值来指示哪个是数据的最新版本。当然,您需要在应用级别上保持标志的一致性。然后,您可以创建使用该标志的索引,如果在where子句中提供该标志,则速度会更快。
优点:
缺点:
需要在应用程序级别维护
否则,您可以依赖于一个单独的历史表,如几个答案中所建议的。
优点:
删除时,在实际数据及其历史记录之间进行数据库级联删除
缺点:
如果您想要完整的历史记录(即,旧数据+当前数据),
什么是最好的将取决于您的用例。我不得不处理一个文档管理系统,在这个系统中,我们希望能够对文档进行版本控制。但我们也有一些功能,比如恢复到旧版本。使用布尔值来加速只需要最后一个的操作会更容易。如果您有真实的历史数据(这些数据永远不会改变),那么专用的历史表可能会更好。
历史的概念适合你的领域模型吗?如果不是,那么您的db架构与您的概念域模型不同。如果在域级别,实际数据和旧数据需要以相同的方式处理,则使用两个表会使设计复杂化。只需考虑需要返回完整历史记录(旧+新)的情况。最简单的解决方案是为每个表都有一个类,但这样就不能像只有一个表那样容易地返回列表。但如果这是两个截然不同的概念,那么让历史在你的设计中成为一流的是很好的。
我还推荐M.Fowler的这篇文章,这篇文章在处理时态数据时也很有趣:Patterns for things that change with time
https://stackoverflow.com/questions/1857977
复制相似问题