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

bin*_*lon 9 database database-design datamodel

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

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

Bra*_*vic 14

介绍

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

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

  • 你是否需要在历史的任何时刻获得整个图的"快照"?
  • 您是否希望永久删除与恢复已删除对象和连接的能力?
  • 你更喜欢速度(并不介意在版本之间复制整个图形)或空间吗?

最重要的是,大多数"支持"表可能也需要"版本感知".

设计

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

在此输入图像描述

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

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

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

查询会是这样的:

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

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

generation: 0

      A0
     /  \
   B0    C0
Run Code Online (Sandbox Code Playgroud)

添加新对象D:

generation: 0 1

      A0
     / | \
   B0  C0 D1
Run Code Online (Sandbox Code Playgroud)

修改A和C并删除B:

generation: 0 1 2

      A0
      A2
     / | \
   B0  C0 D1
   B2* C2

   (*) OBJECT_VERSION.DELETED is true
Run Code Online (Sandbox Code Playgroud)

将C从A移到D:

generation: 0 1 2 3

      A0
      A2
     / |* \
   B0  C0  D1
   B2* C2  |
           C3
Run Code Online (Sandbox Code Playgroud)

等等...

一些冥想

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

"不可变"连接的替代方法是从OBJECT_VERSION继承CONNECTION_VERSION并在其中放置PARENT_ID/CHILD_ID,使用标识关系来确保正确建模菱形依赖关系.如果您需要跟踪移动历史记录,这可能很有用.

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