database - 数据库中的历史记录行管理

标签 database oracle database-design partitioning

像在许多数据库中一样,我正在设计一个数据库,该数据库应记录每个表中更改的行的先前版本。

解决此问题的标准方法是为每个数据表保留一个历史记录表,
并且每当需要在数据表中更新一行时,就会将当前行的副本插入到历史表中,然后会更新数据表中的行。

此解决方案对我的缺点:

  • 维护2个表而不是1个表(如果需要更改表的结构)
  • 应用程序需要知道两个表而不是一个
  • 表的
  • 名称可能需要短一些,以保持表名称和历史记录表名称的约定(例如,SOME_TABLE,SOME_TABLE_HIST)。

    我正在考虑其他解决方案,并且想知道是否可以。
    对于每个表,我们添加一列IS_LAST
  • 当将一行插入表中时,它将以IS_LAST = 1插入。
  • 当更新一行时,原始行的副本将被复制到同一表中,但更改为IS_LAST = 0,并且原始行将根据需要进行更新(仍保持IS_LAST = 1)。

  • 假设在我的情况下,行平均更新10次。
    还假设应用程序执行的操作中至少有90%仅在行的最新版本上发生。

    我的数据库是Oracle 10g,因此为了使“事件”表保持精简,我们可以将表分为2个分区:IS_LAST = 1分区和IS_LAST = 0分区。

    分区是解决历史数据保存问题的好方法吗?

    此解决方案是否将其他分区潜力限制在这些表中?

    谢谢!

    最佳答案

    第一个问题应该是:您将如何处理这些数据?如果您没有明确的业务要求,请不要这样做。

    我做了类似的事情,运行3年后,大约有20%的“有效数据”,其余的是“以前的版本”。它是1000万+ 4000万条记录。在过去的三年中,我们有2(两个)请求来调查更改历史记录,并且两次请求都是愚蠢的-我们记录了记录更改的时间戳,并被要求检查人员是否加类(下午5点之后)。

    现在,我们受困于超大型数据库,该数据库包含没有人需要的80%的数据。

    编辑:

    由于您要求提供可能的解决方案,因此我将介绍我们的工作。这与您正在考虑的解决方案有些不同。

  • 所有表都具有代理主键。
  • 所有主键均从单个序列生成。因为Oracle可以生成和缓存数字,所以效果很好,因此这里没有性能问题。我们使用ORM,我们希望内存中的每个对象(以及数据库中的对应记录)都具有唯一的标识符
  • 我们使用ORM,数据库表和类之间的映射信息以属性的形式出现。

  • 我们将所有更改记录在单个存档表中,并包含以下几列:
  • id(代理主键)
  • 时间戳
  • 原始表
  • 原始记录的
  • ID
  • 用户ID
  • 事务类型(插入,更新,删除)
  • 将数据记录为varchar2字段
  • 这是字段/值对形式的实际数据。

  • 事情是这样工作的:
  • ORM具有插入/更新和删除命令。
  • 我们为所有业务对象创建了一个基类,该基类覆盖了插入/更新和删除命令
  • insert/update/delete命令使用反射以字段名/值对的形式创建字符串。代码查找映射信息,并读取字段名称,关联的值和字段类型。然后,我们创建类似于JSON的内容(添加了一些修改)。创建表示对象当前状态的字符串时,会将其插入存档表。
  • 当新对象或更新对象保存到数据库表中时,它保存到他的目标表中,同时我们将一个具有当前值的记录插入存档表中。
  • 当对象被删除时,我们将其从目标表中删除,同时在归档表中插入一条交易类型为“DELETE”的记录

  • 优点:
  • 我们没有数据库中每个表的存档表。我们也不必担心架构更改时更新存档表。
  • complete归档文件与“当前数据”分开,因此归档文件不会对数据库造成任何性能影响。我们将其放在单独磁盘上的单独表空间中,并且工作正常。
  • 我们创建了2个表单来查看存档:
  • 通用查看器,可以根据存档表上的过滤器列出存档表。用户可以在表单上输入过滤数据(时间跨度,用户等)。我们以字段名/值的形式显示每个记录,并且每个更改都用颜色编码。用户可以查看每个记录的所有版本,还可以查看更改的对象和时间。
  • 发票查看器-这很复杂,但是我们创建了一个表单,该表单显示的发票与原始发票输入表单非常相似,但是带有一些其他按钮,可以显示不同的世代。创建此表单需要花费大量精力。表单使用了几次,然后被遗忘了,因为当前的工作流程中并不需要它。
  • 用于创建存档记录的
  • 代码位于单个C#类中。无需在数据库中的每个表上都使用触发器。
  • 的性能非常好。在高峰时间,大约有700-800个用户使用该系统。这是ASP.Net应用程序。 ASP.Net和Oracle都在一个具有8Gb RAM的双XEON上运行。

  • 缺点:
  • 单表归档格式比每个数据表都有一个归档表的解决方案更难读。
  • 在存档表中非id字段上搜索
  • 很难-我们只能在字符串上使用LIKE运算符。

  • 因此,再次检查存档的要求。这不是一项艰巨的任务,但是收获和使用却很少。

    关于database - 数据库中的历史记录行管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/715811/

    相关文章:

    sql - 如何使用 CTE 和 INNER JOIN 删除行?

    mysql - 从模型进行正向工程后,如何自动执行 MySQL 脚本或例程

    Oracle 词汇,什么是 mysql/SQL Server 相当于数据库

    mysql - 将 select 和 dateadd 函数的结果集插入到同一个表中

    mysql - 大数据量数据库设计

    mysql - 整个表存储在索引中

    mysql - 各个互联域的用户是否应该放在同一个数据库表中?

    php - 数据插入前数据库数据字段检查

    c# - Oracle 更新表中的重复行

    java - DatabaseMetaData.getTables() 返回多少列?