【问题标题】:Database Historization数据库历史化
【发布时间】:2012-06-12 05:58:52
【问题描述】:

我们的应用程序有一个要求,我们需要在其中存储引用以供以后访问。

示例:用户可以一次提交一张发票,并且该发票包含的所有参考资料(客户地址、计算的金额、产品描述)和计算应该随着时间的推移而存储。

我们需要以某种方式保存引用,但是如果 e.g.产品名称更改?因此,我们需要以某种方式复制所有内容,以便稍后记录,并且不受将来更改的影响。即使产品被删除,也需要稍后在存储发票时进行审核。

关于数据库设计的最佳实践是什么?即使是最灵活的方法,例如当用户想稍后编辑他的发票并从数据库中恢复它?

谢谢!

【问题讨论】:

    标签: mysql database-design


    【解决方案1】:

    这是一种方法:

    基本上,我们从不修改或删除现有数据。我们通过创建一个新版本来“修改”它。我们通过设置 DELETED 标志来“删除”它。

    例如:

    • 如果产品更改了价格,我们会在 PRODUCT_VERSION 中插入一个新行,而旧订单会保持与旧 PRODUCT_VERSION 和旧价格的关联。
    • 当买家更改地址时,我们只需在 CUSTOMER_VERSION 中插入一个新行并将新订单链接到该行,同时保持旧订单链接到旧版本。
    • 如果产品被删除,我们并没有真正删除它 - 我们只是设置 PRODUCT.DELETED 标志,因此该产品的所有历史订单都保留在数据库中。
    • 如果客户被删除(例如,因为他要求取消注册),请设置 CUSTOMER.DELETED 标志。

    注意事项:

    • 如果产品名称需要唯一,则无法在上述模型中以声明方式强制执行。您要么需要将 NAME 从 PRODUCT_VERSION“提升”到 PRODUCT,将其设为密钥并放弃“演变”产品名称的能力,要么仅在最新的 PRODUCT_VER 上强制唯一性(可能通过触发器)。
    • 客户的隐私存在潜在问题。如果客户从系统中删除,可能需要从数据库中物理删除其数据,而仅设置 CUSTOMER.DELETED 不会这样做。如果这是一个问题,要么清空所有客户版本中的隐私敏感数据,要么断开现有订单与真实客户的连接,并将它们重新连接到特殊的“匿名”客户,然后物理删除所有客户版本。李>

    此模型使用大量识别关系。这会导致“胖”外键,并且可能是一个存储问题,因为 MySQL 不支持前沿索引压缩(不像 Oracle),但另一方面 InnoDB always clusters the data 在 PK 上,这种集群可以有利于性能。此外,JOIN 的必要性也较低。

    具有非识别关系和代理键的等效模型如下所示:

    【讨论】:

    • 要拥有唯一的产品名称,您可以添加一个只有产品名称的表,其中名称是 pk,并从 PRODUCT_VERSION 链接到该表
    • @OweJessen 当然,您可以拥有具有唯一名称的 LATEST_PRODUCT_VERSION 表,但这不能算作“声明性”解决方案,因为您需要手动插入和删除该表中的行,因为新产品版本是创建。除非您使用的 DBMS 可以自动更新物化视图并对其强制执行唯一性(例如 MS SQL Server 的索引视图),否则 DBMS 本身会为您维护 LATEST_PRODUCT_VERSION。
    【解决方案2】:

    您可以在产品表中添加一列,指示它是否正在销售。然后,当产品被“删除”时,您只需设置标志,使其不再作为新产品提供,但您保留数据以供将来查找。

    要处理名称更改,您应该使用 ID 来指代产品,而不是直接使用名称。

    【讨论】:

    • 如果他想在历史上包含销售时的产品名称,那么第二点对他没有帮助。假设相同的 ItemId 在 1988 年之前适用于“Coke”,然后适用于“Coke Classic”,他想知道在旧订单上它被称为“Coke”。您的建议是他试图避免的 - 他使用标准化数据生成的任何报告都会在所有订单上显示“Coke Classic”,无论是否在 1988 年之前。
    • True .. 解决这个问题的一种方法是为名称更改创建一个新产品,或者添加另一个表来跟踪产品名称(这接近 @Branko Dimitrijevic 的解决方案)。
    【解决方案3】:

    您在纯粹主义和实用主义方法之间展开了一场永恒的争论。

    从数据库规范化的角度来看,您“应该”保留所有相关数据。换句话说,假设产品名称发生更改,请保存更改日期,以便您可以及时返回并使用该产品名称以及当天存在的所有其他数据重建您的发票。

    “去”规范化的方法是将发票视为“时刻”,在相关表格中记录当天的实际数据。这种方法可以让您在没有任何依赖关系的情况下提取该发票,但您永远无法从头开始重新创建该发票。

    【讨论】:

      【解决方案4】:

      您所面临的问题是,我相信您知道,这是数据库规范化的结果。解决此问题的方法之一可以从商业智能技术中获取 - 将处于非规范化状态的数据归档到 Data Warehouse

      标准化数据:

      • 订单表
        • 订单编号
        • 客户 ID
      • 客户表
        • 客户 ID
        • 名字
      • 物品表
        • 物品编号
        • 项目名称
        • 商品价格
      • 订单明细表
        • ItemDetailId
        • 订单编号
        • 物品编号
        • 项目数量

      去规范化查询和存储时,数据仓库表的样子

      • 订单编号
      • 客户 ID
      • 客户名称
      • 客户地址
      • (其他客户字段)
      • ItemDetailId
      • 物品编号
      • 项目名称
      • 商品价格
      • (其他 OrderDetail 和项目字段)

      通常情况下,要么有某种计划的作业按计划将规范化数据中的数据提取到数据仓库中,要么如果您的设计允许,它可以在订单达到特定状态时完成。 (例如已发货)可能会在每次状态更改时存储记录(使用名为 OrderStatus 的字段跟踪当前状态),因此完全非规范化的数据可用于操作/履行过程的每个步骤。将数据归档到仓库的时间和方式将根据您的需要而有所不同。


      上面涉及很多开销,但我知道的另一种常见方法会带来更多开销。

      另一种方法是将表设为只读。如果客户想要更改他们的地址,您无需编辑他们现有的地址,而是插入一条新记录。

      因此,如果我在 Jamnuary 首次在您的网站上订购时的地址是 AddressId 12,那么我会在 7 月 4 日搬家,我会收到一个与我的帐户绑定的新 AddressId。 (说 AddressId 123123,因为您的网站非常成功并且吸引了大量客户。)

      我在 7 月 4 日之前下的订单的 AddressId 为 12,而在 7 月 4 日或之后下的订单的 AddressId 为 123123。

      对需要保留历史数据的每个表重复该模式。


      我确实有第三种方法,但很难搜索。我只在一个应用程序中使用它,它实际上在这个单一实例中运行良好,它具有一些非常具体的业务需求,可以完全按照特定时间点的方式重建数据。除非我有类似的业务需求,否则我不会使用它。

      在特定状态下,将数据序列化为 Xml 文档或其他可用于重构数据的文档。这使您可以将数据保存为序列化时的数据,保留原始表结构和关系。

      【讨论】:

      • 是的....@David Stratton 所说的...删除了我对同一想法的更通俗的回答。
      • @Greg P - 我要投票给你。您的回答更简洁,仍然具有相关性。
      • 将其添加回来以供后代使用...当有更简洁的答案时,不要重复,谢谢。
      【解决方案5】:

      当您拥有对时间敏感的数据时,您可以使用 product 和 Customer 表作为查找表,并将信息直接存储在 Orders/orderdetails 表中。

      因此,订单表可能包含客户姓名和地址,详细信息将包含有关产品的所有相关信息,尤其是价格(您永远不想依赖产品表来获取超出初始查找时间的价格信息)命令)。

      这不是非规范化,数据会随时间变化,但您需要历史值,因此您必须在创建记录时存储它,否则您将失去数据完整性。您不希望您的财务报告突然显示您去年的销售额增加了 30%,因为您有价格更新。那不是你卖的。

      【讨论】:

      • "这不是反规范化..." 没错。在关系系统中,重复数据意味着“具有相同含义的相同值”。在这里,值可能相同,但含义不同。 (例如,当前价格与订购时的价格。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 2010-10-18
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      相关资源
      最近更新 更多