存储git就像提交更改历史记录一样

时间:2014-03-17 09:47:39

标签: postgresql neo4j

我想为我的数据库实体构建一个类似于版本控制系统的git。

模型将是:

Commit
  parent_commit_id

Change
  entity_id
  commit_id
  modifier (added, deleted, modified)

Entity

实体永远不会被删除,因此用户可以撤消提交并最终获得有效状态。

听起来很简单,但是:

  • 用户每次点击都会生成一次提交(性能非常重要)
  • 每次提交都会有大约100次更改(修改,添加或删除)

因为我们只是存储更改,所以必须计算或存储当前状态。

选项1 :保存每次提交的完整状态意味着我不仅会在提交中存储修改,添加和删除,还会存储未更改的每个实体。我认为这不是一个真正的选择,因为系统运行时将有超过2000万个实体。

选项2 :使用递归公用表表达式计算当前状态。我不知道这是否足够快......

选项3 :在一段时间后执行清理(如git gc)。这意味着我实际上会删除在清理时不再有效的所有实体。不是一个选项,因为我希望能够看到所有的变化并回到那些变化。

选项4 :使用图表数据库(neo4j)?它能以合理的性能处理这样的指定吗?

你还有其他想法吗?

2 个答案:

答案 0 :(得分:4)

您使用Neo4j的想法非常有趣。快速阅读http://en.wikibooks.org/wiki/Git/Internal_structure已经显示了git的复杂程度,以及提交拓扑是一个“有向无环图”的事实,它支持Neo4j。

但要考虑的一件事是你计划的模型有多复杂?你想要git的部分或全部复杂性吗?如果是这样的话,像Neo4j这样的灵活数据库将是一个好主意。

如果您只想要跟踪单个文件更改的内容,而不考虑多个并发用户,那么请考虑存储最新文件的旧RCS系统以及先前版本的差异链。这可以很容易地存储在两个表中(一个用于文件,一个用于更改)。这是Dan的答案的相反方向,它存储第一个文件和那里的变化。两种方式都有效,但RCS方式能够比旧版本更快地检索最新版本,而视频方法可以最快地检索旧版本。既然您从最旧到最新观看视频,那么它们就是这样做的,但我认为对于文件修订,您通常需要最新的视频。有关这些方法的更全面的评论,请查看Martin Fowlers博客Event Sourcing。但是,这些方法并不真正考虑多个并发用户或任何复杂的用户。但它们可能是更多的基础。

因此,让我们重新考虑更复杂的模型。 Neo4j是无架构的,允许您根据需要开始简单和增强功能。例如,您可以遵循以下路线:

  • 构建一个简单的类似RCS的文件修订系统,其中包含单个图形节点中的最新内容,以及指向旧版本(或旧版本差异链)链接的链接
  • 然后你决定需要支持多个文件的提交,添加树对象(在http://en.wikibooks.org/wiki/Git/Internal_structure中描述),这些可以是图中的真实树结构,图形节点链接到文件对象节点
  • 这些树由提交对象引用,提交对象本身以链式链接,与先前的提交相关联。一旦拥有这些提交链,您可能就不再需要文件链,因为您将遍历提交链。每个提交都指向一个指向文件的树。
  • 然后您可能决定支持分支,因此您添加了标记和分支对象,这些对象链接到提交(以及树和文件)。这自然导致了非循环有向图,显示了随时间发生的分支和合并。
  • 然后你甚至可以考虑添加reflogs,它们也可以建模为图形。

当您浏览上面的列表时,总图表变得更丰富,更复杂,支持更多的用例。我认为这是构建数据模型的好方法。

从阅读http://en.wikibooks.org/wiki/Git/Internal_structure可以清楚地看出,即使提供了简化的描述,我们也可以看到建模中的大部分价值都是图形。链表,树和非循环有向图。对我来说听起来像Neo4j这是一个很好的技术。

那么如何开始?例如,看一下Graph Gist Examples的某些内容。这里看起来很简单的一个简单的是Simple versioning nodes scheme。然后从那里开始构建。

答案 1 :(得分:1)

我必须仔细考虑一些细节 - 但是,如果你从视频处理中吸取教训 - 有原始的签到,并且每个版本都有delta,但是有一个'keyframe'属性可以指示完整快照,每个,10个提交,总是最新版本。为您提供良好的性能组合,无需为每次提交存储完整数据......