我们的应用程序中需要存储引用以供以后访问.
示例:用户可以一次提交发票,并且应该随时间存储此发票包含的所有参考(客户地址,计算的金额,产品描述)和计算.
我们需要以某种方式保留参考文献,但如果产品名称有变化吗?因此,某种程度上我们需要复制所有内容,以便以后记录,不会受到未来变化的影响.即使删除了产品,也需要在存储发票时进行审核.
这里有关数据库设计的最佳实践是什么?即使是最灵活的方法,例如当用户想要稍后编辑发票并从数据库恢复时?
谢谢!
从本质上讲,我们从不修改或删除现有数据.我们通过创建新版本来“修改”它.我们通过设置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并且这种群集可能是有益的为了表现.此外,JOINs不太必要.
具有非标识关系和代理键的等效模型如下所示: