我们正在构建一个SaaS产品,用户可以从各种类型的交易中产生成本,例如:
- 拨打电话
- 发送短信
- 存储录音
我们已经构建了我们的系统来存储每个服务的成本,例如call_audit
表如下所示:
Date Call ID Our Cost User Cost Currency Duration User ID
---------- -------- --------- --------- -------- -------- -------
2018-01-02 sm_123 0.01 0.02 USD 72 us_1
sms_audit
表如下所示:
Date SMS ID Our Cost User Cost Currency User ID
---------- -------- --------- --------- -------- -------
2018-01-02 sm_123 0.01 0.02 USD us_1
然后有一个包含用户付款和退款的payment_audit
表:
Date User ID Amount Currency Type
---------- -------- ------ -------- ----
2018-01-02 us_1 12 USD CHARGE
2018-01-02 us_1 -2 USD REFUND
我们还有一个带有balance
列的user
表,当用户产生电话,短信费用或退款时,我们会减少该列。当用户向帐户付款时,我们会将其递增(CHARGE
如上所述(。
但展望未来,我认为我们需要比在代码中更新的单个余额数字更具弹性的东西。
一项改进是使用触发器而不是在代码中更新余额数字。
另一种方法是计算用户在多个表中的总成本和付款,并对批次求和。随着表格增长到许多 1000 个事务,我可以想象这成为一个缓慢的计算。
我们想到的另一种方法是有一个balance_transactions
表,其中包含debit
、credit
并运行balance
列。这当然会导致行之间的传递依赖关系,如果寻求一个很好的规范化数据库,这不是很好。这也意味着我们正在复制数据,但在现实世界中,这是一个可以接受的权衡吗?
通过使用实例化视图,可以避免重复数据。请注意,更新余额(以任何方式 - 通过应用程序、触发器、部分运行余额(已经复制了数据。因此,您应该运行一些验证过程来提醒差异。这样的验证过程应该完成所有计算,所以它们也可以填充物化视图。
但是,实际解决方案取决于您需要这些数据的频率。例如,如果您每月获取所有客户余额以开具发票,请不要复制它们。但是,如果您在每次客户操作后打印余额,例如在某种交易确认中(例如生成并通过电子邮件发送给客户的 PDF(,您可能希望以呈现给客户的形式保留运行余额,因为他拥有余额证据。