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

13

我正在寻求有关围绕版本化数据设计数据模型的最佳方式的意见。将存在一对多和多对多的关系,这些关系在每个版本中都可能发生变化。

我正在寻求不同的策略,最终目标是进行高效的比较,并尽可能地仅存储增量。

1个回答

18

简介

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

版本控制对象很容易,但跟踪它们之间的连接就不那么容易了 - 您需要做出一些设计决策。例如:

  • 您是否需要在历史的任何时刻获取整个图形的“快照”?
  • 您想要永久删除还是能够恢复已删除的对象和连接?
  • 您更喜欢速度(并且不介意在版本之间复制整个图形)还是空间?

此外,大多数“支持”表格可能也需要“版本控制感知”。

设计

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

enter image description here

OBJECT和CONNECTION之间的符号是 "category" (也称为继承、子类、泛化层次结构等)。

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

  • 整个图形具有全局版本(即“代”的概念),我们仅存储它们之间的增量。
  • 每个对象都具有该全局代数(而不是本地、对象特定的版本)。
  • 连接也是对象,因此它们也具有版本。
  • 每当一组对象进入资源库时,都会插入一个新GENERATION,并且:
    • 插入的对象将被插入到OBJECT和OBJECT_VERSION中。
    • 修改的对象将被插入到OBJECT_VERSION中。
    • 已删除的对象将被插入到OBJECT_VERSION中,并将DELETED设置为true。
    • 恢复的对象将被插入到OBJECT_VERSION中,并将DELETED设置为false。 顺便说一句,这使得可以多次重复删除/还原周期。
    • 其余对象都不变,因此我们不浪费空间来复制未更改的数据。
  • 连接实际上无法进行修改。 要“移动”子对象到新父对象,删除旧连接(通过按上述方式设置DELETED)并插入新连接。 实际上,删除是连接支持的唯一一种修改类型。

查询过程如下:

  • 要从其所有版本中获取单个对象,请选择仍不高于所需代数的最高版本。 如果此版本的DELETED为true,则此代中不存在该对象。
  • 要在所需代数中获取整个图形的快照,请为所有对象执行上述操作,并创建内存中的图形。 消除一个或两个端点都是DELETED的连接。
  • 要获取连接到给定对象的对象,请递归遍历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,使用标识关系来确保正确建模菱形依赖。如果需要跟踪移动的历史记录,则可能会有所帮助。

当然,这只是笼统的概述,希望您能找到自己的路线...


这些版本是互相独立的。也许"版本"这个词并不太准确,更多的是指父子层次结构。 - binarymelon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接