【问题标题】:How to design a SQL db with undo-redo?如何设计带有 undo-redo 的 SQL 数据库?
【发布时间】:2011-07-23 07:24:23
【问题描述】:

我试图弄清楚如何设计我的数据库表以允许撤消重做。

假设您有一个具有以下结构的 tasks 表:

id <int>
title <varchar>
memo <string>
date_added <datetime>
date_due <datetime>

现在假设在几天内多次登录并进行了多次编辑;但用户想回到其中一个版本。

  1. 您是否有一个单独的表来跟踪更改 - 或者 - 您是否尝试将更改保留在 tasks 表中(“幽灵”行,因为没有更好的术语)?
  2. 您会跟踪所有列还是只跟踪每次更改的列?

如果重要的话,我正在使用 MySQL。另外,如果重要的话,我希望能够显示历史记录(ala Photoshop)并允许用户切换到任何版本。

额外问题:您会在更改时保存整个 memo 单元格还是尝试仅保存增量?我问的原因是因为memo 单元格可能很大,并且每次修订只能更改一个单词或字符。诚然,保存 delta 需要解析,但如果不希望经常撤消,那么节省空间而不是处理时间不是更好吗?

感谢您的帮助。

【问题讨论】:

标签: mysql sql undo-redo delta audit-tables


【解决方案1】:

我会为您的任务表创建一个历史记录表。与任务相同的结构 + 一个名为 previousId 的新字段。这将保存以前的更改 ID,因此您可以通过不同的更改(撤消/重做)来回返回。

为什么要使用新的历史记录表?原因很简单:不要让 tasks 表中的东西不适合它。

至于空间,在历史记录中,而不是备忘录,使用二进制格式并压缩要存储的文本内容。不要试图检测变化。你会遇到一个错误的代码,这会导致沮丧和浪费时间......

优化: 更好的是,您可以在 History 表中只保留三列: 1. taskId(任务的外键) 2. 数据 - 一个二进制字段。在历史表中保存之前,创建一个 XML 字符串,其中仅包含已更改的字段。 3. previousId(将有助于维护更改队列并允许来回导航)

对于数据字段,创建一个这样的 XML 字符串:

<task>
  <title>Title was changed</title>
  <date_added>2011-03-26 01:29:22<date_added>
</task>

这基本上会告诉您,这次您只更改了标题和 date_added 字段。

XML 字符串生成后,如果需要,只需将其压缩并存储到历史表的数据字段中。

XML 也将允许灵活性。如果您在任务表中添加/删除字段,您也不需要更新历史表。这样一来,tasks 表和 History 表的结构就解耦了,不需要每次都更新两个表。

PS:不要忘记添加一些索引以快速浏览历史表。要索引的字段:taskId 和 previousId,因为您需要对此表进行快速查询。

希望这会有所帮助。

【讨论】:

  • 顺便说一句,压缩会将您的文本大小减少到原始文本的 5%。一个常见的值是 10% 左右,但如果你有常见的重复词,你会得到更好的压缩。
  • 这很聪明,但我不确定我是否理解“3 个字段”的想法。当然,历史表中的每条记录都必须有自己的 ID 字段(自动增量)、任务记录 ID 的外部链接以及对先前历史记录 ID 的引用(如果适用)(即具有相同的任务记录 ID)...还是有什么我不明白的地方?
  • @mikerodent 我想你明白了,我们需要 2 个键:一个到任务表 (taskId),一个到历史表 (previousId) 加上改变的有效负载(数据),这样你就可以能够根据 taskId 和 previousId 字段浏览历史记录,还能够访问已更改的数据并在需要时恢复它。
【解决方案2】:

您可能希望以增量形式压缩修订,但您仍应拥有完整的当前修订以便快速检索。

但是,从旧到新的增量需要大量处理,除非您有一些非增量可作为基础。每次发生变化时,较新到较旧的增量都需要重新处理。因此,增量通常不会为您带来很多好处,而是会带来更大的复杂性。

上次我检查是几年前,MediaWiki,Wikipedia 背后的软件,存储了全文并提供了一些方法来使用 gzip 压缩旧版本以节省空间,并提供了一个专用表 archive 用于删除的修订/页面.

他们的网站上有一个ER diagram of their database layout,您可能会觉得它很有用。

【讨论】:

    【解决方案3】:

    当我使用 SQL 做类似类型的事情时,我总是使用第二个表来记录修订历史。这可以防止您的主表在版本中变得过大。理由是检索当前记录几乎 100% 发生,查看历史记录和回滚(撤消)非常罕见。

    如果您只有一个 UNDO 或历史记录,那么在表中跟踪可能没问题。

    您是要保存增量还是整个单元格取决于预期的增长/使用情况。如果您愿意创建管理增量的逻辑,那将节省您的空间。如果事情没有真正创造出我通常不会开始的新版本,(应用 YAGNI)

    【讨论】:

      猜你喜欢
      • 2013-02-25
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      • 2017-03-30
      相关资源
      最近更新 更多