为版本化数据设计数据模型

时间:2012-10-19 17:53:33

标签: database database-design datamodel

我正在寻找关于设计围绕版本化数据的数据模型的最佳方式的一些输入。将存在一对多和多对多关系,这些关系可以在不同版本之间发生变化。

我正在寻找一些不同的策略,最终目标是进行有效的比较,如果可能的话,只存储delta。

1 个答案:

答案 0 :(得分:14)

简介

这实际上是一个相当困难的问题。

版本控制对象很简单。它们之间的版本连接不是那么多 - 你必须做出一些设计决定。例如:

  • 您是否需要随时获取整个图表的“快照”?
  • 您是否希望永久删除与还原已删除对象和连接的能力?
  • 您更喜欢速度(并且不介意在版本之间复制整个图形)或空间吗?

最重要的是,大多数“支持”表格可能也需要“版本感知”。

设计

如果我是你,我可能会从以下起点开始:

enter image description here

OBJECT和CONNECTION之间的符号是"category"(又称继承,子类,泛化层次等)。

这种设计背后的基本思想是支持“快照”,“恢复”和“增量”功能:

  • 整个图表有一个全局版本(又名“生成”),我们只存储它们之间的增量。
  • 每个对象都使用该全局生成版本(与本地特定于对象的版本相对)。
  • 连接是对象,也可以对它们进行版本控制。
  • 每次一组对象进入存储库时,都会插入一个新的GENERATION并且:
    • 插入的对象插入OBJECT和OBJECT_VERSION。
    • 将修改后的对象插入OBJECT_VERSION。
    • 删除的对象插入到OBJECT_VERSION中,DELETED = true。
    • 将已还原的对象插入OBJECT_VERSION,DELETED = false。顺便说一句,这使得删除/恢复周期可以重复多次。
    • 其余的对象都不受影响,因此我们不会浪费空间复制未更改的数据。
  • 无法真正修改连接。要将子对象“移动”到新父对象,请删除旧连接(通过如上所述设置DELETED)并插入新连接。实际上,删除是连接支持的唯一一种修改。

查询将会是这样的:

  • 要获得单个对象,在其所有版本中,选择仍然不高于所需代数的最高对象。如果此版本的DELETED为true,则此代中不存在object。
  • 要在所需的代中获取整个图的快照,请对所有对象执行上述操作并创建内存中图。消除其中一个或两个端点都已删除的连接。
  • 要获取连接到给定对象的对象,请递归遍历CONNECTION,但在遇到不符合上述条件的对象时立即剪切递归。

实施例

假设您必须放置对象A,B和C,其中A是B和C的父对象:

generation: 0

      A0
     /  \
   B0    C0

添加新对象D:

generation: 0 1

      A0
     / | \
   B0  C0 D1

修改A和C并删除B:

generation: 0 1 2

      A0
      A2
     / | \
   B0  C0 D1
   B2* C2

   (*) OBJECT_VERSION.DELETED is true

将C从A移至D:

generation: 0 1 2 3

      A0
      A2
     / |* \
   B0  C0  D1
   B2* C2  |
           C3

等等...

一些冥想

此设计对具有不一致删除的异常开放:数据库不会保护自己不连接已删除和未删除的对象,或者将其中一个对象演变为已删除状态而不删除连接。在检查两个端点之前,您不会知道连接是否有效。如果您的数据是分层的,则可以使用“可达性模型”:如果可以从某个根对象访问对象,则不会删除该对象。您永远不会直接删除该对象 - 您只需删除它的所有连接。这适用于层次结构,例如文件夹/文件或类似文件,从“顶部”开始,向底部搜索,直到找到所需的对象。

“不可变”连接的替代方法是从OBJECT_VERSION继承CONNECTION_VERSION并在其中放置PARENT_ID / CHILD_ID,使用标识关系来确保diamond-shaped dependency is correctly modeled。如果您需要跟踪移动历史记录,这可能很有用。

这些只是广泛的笔触,我希望你能找到自己的方式......