在高度规范化的数据库中选择表数据的通用版本控制策略

时间:2009-03-03 11:32:20

标签: database database-design version-control

对于长篇大论的标题感到抱歉,但要求/问题是相当具体的。

参考下面的示例(但非常简化)结构(在伪造的SQL中),我希望能更好地解释它。

TABLE StructureName {
  Id GUID PK,
  Name varchar(50) NOT NULL
}

TABLE Structure {
  Id GUID PK,
  ParentId GUID,                 -- FK to Structure
  NameId GUID NOT NULL           -- FK to StructureName
}

TABLE Something {
  Id GUID PK,
  RootStructureId GUID NOT NULL  -- FK to Structure
}

可以看出,Structure是一个简单的树结构(不担心为这个问题排序孩子)。 StructureName是翻译系统的简化。最后,“Something”只是引用树根结构的东西。

这只是需要进行版本化的许多表格中的一个,但是这个表格在大多数情况下都是一个很好的例子。

需要对Structure表的名称和/或树'布局'的任何更改进行版本控制。以前的版本应始终可用。

似乎有一些可能性来解决这个问题,比如复制整个结构,但大多数方法都会导致一个“松散”的参照完整性。例如,如果遵循这种方法,则必须复制“Something”记录,假定根结构将是新记录,并且具有新ID。

可能的解决方案的其他途径正在研究Wiki如何处理这一问题或进一步研究如何正确处理版本控制系统的工作方式。

目前,我觉得如何以通用的方式继续这一点我感到有点无能为力。

任何想法都将不胜感激。

由于

leppie

2 个答案:

答案 0 :(得分:10)

一些简单的想法:

完整副本:创建结构的副本,但是对于每个表,向PK​​和所有FK添加version_id列;因此,您可以使用完整的参照完整性创建生命数据的副本。

  • 亲:易于查询历史记录
  • con:大量(复制的冗余数据)

更改副本:仅复制实际更改的内容以及valid_from / valid_to数据。

  • pro:低数据量复制
  • con:难以查询,因为必须间隔加入

变体:这适用于两种方案。您可以将当前记录保存在与旧版本相同的表中,而不是创建结构的副本,而是将其标记为当前记录。

  • pro:数量较少的表格,更容易混合历史记录和当前信息
  • con:正常操作在更大的表上运行,这将导致性能影响

审核日志:根据您的实际要求,只需创建如下审核跟踪就足够了:

id,  timestamp,  changed_table,  changed_column,  old_value,  new_value,  changed_by

您可以将其扩展为完整的表结构:

transaction,  table_change,  changed_column
  • pro:generic,因此很容易为大量表格实现
  • con:如果你需要在给定时间重建一组记录的状态,查询将成为一场噩梦

我写了a blog about various approaches to versioning,但要注意:它是用德语写的。

答案 1 :(得分:6)

数据仓库人员有几种“缓慢变化维度”的算法。

更复杂的算法提供围绕维度值的数据范围,以指示它何时有效。

根据您的版本控制要求,您可以执行其中一项操作,这些内容来自Kimball的数据仓库工具包。

  1. 为结构表的行分配版本号。这意味着你必须做一些推理来收集一个完整的结构。它包括与早期版本中未更改的行联合的选定版本号。

  2. 为结构表的行指定日期范围或版本范围。这意味着某些行具有开始日期和结束日期;在不可能的未来,某些行将在某个时代有结束日期。或者,如果您使用版本号,您将拥有一个起始端对或一个起始无穷大对,表明该行仍然是当前的。然后,您可以轻松查询“今天”有效的行或应用于请求的版本。

  3. 克隆每个版本的结构。这令人不愉快,因为克隆操作很昂贵。但是,查询是微不足道的,因为整个结构可以使用单个一致的版本号。