您如何设计用于在 NoSQL 中跟踪更改历史记录的模式?

Dan*_*iel 7 nosql

我正在考虑为一个需要跟踪更改的项目尝试一个文档存储数据库。我想用 firebase 做原型,但我认为模式/实现在 MongoDb 中是一样的

(简化的)设置是我有三个表/集合ProjectAssetUser. A(登录)User可以更改(创建、更新或删除)aProjectAsset. 的Asset可分配给(最大的一个)Project

任何时候AssetProject有任何更改,我都想捕获User进行更改的时间,更改时间,以及在大多数情况下之前的状态。

Mic*_*een 5

向项目和资产文档添加三个属性 - WrittenWhenWrittenByIsActive。将这些填充到“真实”数据中。

\n\n

当记录更改时,会复制它,但 IsActive 标志会翻转。WrittenWhen保留和的原始值WrittenBy。原始记录将使用修改用户的 ID 和时间戳进行更新。我这样做是为了让保存该记录的 magic id 的任何其他记录保留该指针。

\n\n

读取时仅查找具有正确 IsActive 值的记录。

\n\n

如果存档记录写入单独的集合/命名空间/数据库/无论您的技术支持什么,则可以省略 IsActive。

\n\n
\n\n
\n

谢谢迈克尔,我对这个实施有一些担忧;大小 - 这可能有很多冗余数据,可能会存储比需要的数据多 100 倍或更多的数据,对于许多使用 mongodb 的部署来说,这可能不是问题,但是对于像 Firebase 这样的 BaaS,这可以使巨大差距。我的另一个担忧是,它不知道哪个数据点被编辑,除非您与之前的数据点进行比较,并且多个用户编辑多个数据点的可能性,要显示“最后更新者为* on * ”,它可能需要查找许多旧记录 \xe2\x80\x93 Daniel 3 月 10 日 16:16

\n
\n\n

您提出的观点是有效的。另一种设计是仅将更改的值存储在历史存储中。然后会有一条记录(主键字段、更改字段的名称、旧值、新值、写入者、写入时间)。仅存储已更改的部分会直接导致两个新问题。

\n\n

第一,您必须承担为每次写入分离更改部分的强制性开销,而不是将差异成本推迟到需要时。通常,我们希望 OLTP 写入速度快,并且审计报告对性能不是至关重要的。因此,在我看来,将这项工作推迟到需要报告时再进行是合理的。当然,写入整个记录的成本将高于写入较短的仅比较记录的成本。您可以对您的基础设施进行基准测试,看看这是否重要。

\n\n

第二,通过仅存储增量,您会丢失发生更改的数据上下文。我的意思是,通过仅存储增量,我们可以读取单个审计记录来查看字段 53 从“A”更改为“B”。发生更改时所有其他字段的值是什么?要找到答案,您必须向后阅读历史记录,直到找到您感兴趣的其他字段的最新值,可能一直到“实时”记录。同样,我不知道这是否是您的场景的有效用例,或者更改频率和审核读取频率是否会使其成为问题,但这是值得考虑的事情。

\n\n

使用任一方案显示“最后更新者为..于..”都是对最后写入的历史记录的单个记录查找,因为这两种方式都将此信息存储在每个历史记录上。要查找存储的完整记录发生的变化,需要进行第二次读取和比较,而增量存储不需要这样做。重建历史记录对于完整记录来说是轻量级的工作,对于增量数据来说是繁重的处理工作。

\n\n

我不太了解您的要求或限制,无法充分评估一种设计与另一种设计的比较。由于易于实施和(可能)性能,我更喜欢我记录的那个。不过,我要指出的是,天下没有免费的午餐。这项工作必须在某个时间、某个地方完成。

\n