【问题标题】:Calculating running balance from join table [SQL Database Design]从连接表计算运行余额【SQL数据库设计】
【发布时间】:2017-01-11 04:52:03
【问题描述】:

假设我有三张桌子

交易

  • 金额
  • 日期

记录

  • 金额
  • 日期

CUSTOM_RECORDS

  • 金额
  • 日期

(假设还有许多其他字段可以证明拆分这些表是合理的)

要计算运行余额,我有两种方法

-------------方法1 -------------

重读,轻写

每当我们阅读时,只需加入表格,按日期排序并计算运行余额。

专业版

  • 写起来很简单,写到每个表里就行了

骗局

  • 读取非常繁重,每次读取都需要进行计算。 查询(假设是 1 周的跨度)并对所有记录进行计算是非常奇怪的。如果我查询 10 条记录,则需要对 100 万条记录进行计算才能知道 10 条记录的余额。

-------------方法2 -------------

写重,读轻

我还有一张桌子

FINAL_TABLE

  • 日期
  • 金额
  • 流动余额

每当我写的时候,我都会刷新这个表并重新计算所有的流动余额。

专业版

  • 读取很容易,已经计算了运行余额。
  • 时间段之间的查询就像从 FINAL_TABLE 中提取时间跨度之间的日期一样简单

骗局

  • 写入真的很慢,对三个表中的任何一个的每次写入都意味着刷新整个 FINAL_TABLE 表!

我为什么不直接重复使用最新的运行余额?如果条目保证在现实生活中按时间顺序排列,则可能会发生这种情况。但是,有时可能会延迟添加条目。

目前,我正在使用方法 2,每次客户端将一行保存/更新到三个表中的任何一个时,服务器都会在尝试刷新和计算 FINAL_TABLE 时冻结。显然,这不是非常可扩展的。

方法 1 在查询方面也不是很可扩展。我必须从一开始就计算运行余额才能知道上周的运行余额。

这两种方法的可扩展性都不是很好。什么是确保可扩展性和相对快速的读写性能的良好设计?银行使用什么方法来跟踪流动余额?

【问题讨论】:

    标签: sql database postgresql database-design


    【解决方案1】:

    这取决于。

    假设您有一个类似transaction report 的报告,其中将显示帐户的运行余额。如果你想显示实时数据,那么总是method 1 会更好。我建议为此使用Quirky Update,而不是使用cursorsloopssub-queriesrecursions

    另一方面,如果您不需要实时运行总计,那么您可以使用 method 2 并进行一些自定义。我不支持在您进行交易时更新Final Table。而不是我建议用间隔时间表更新它。根据您的流量或负载,您可以在一段时间后更新运行总数。

    我不建议实时使用method 2,因为这会使您的交易成本高昂。

    为了让您的method 1 更快,这里有一些链接。

    Calculating Running Total

    Quirky Update

    Quirky Update Performance

    Halloween Protection

    Create Table AccBalance
    (
        AccountNO PK,
        Balance
    )
    
    Create Table AccDateWiseCumBalance
    (
        AccountNO PK,
        SystemDate PK,
        Cumulative Balance
    )
    

    每笔交易都会更新第一张表,将保持实时余额,但不保留任何历史记录。

    第二张表记录帐户和日期累计余额,将在每天结束时更新。

    因此,如果您需要截至上一个日期的累积余额,您将从第二个表中检索数据。

    如果您需要截至当前日期的累积余额,您将从第二个表中检索截至当前日期前一天的数据,并从第一个表中检索当前日期数据。

    【讨论】:

    • 您好,感谢您的回复!方法 1 的问题是,如果您查询上周的 transaction report 怎么办?您不需要计算所有行以便获得上周的报告吗?
    • 对于这种情况,我们使用这两种方法。在我们的系统中,我们保留了这两种方法。我正在为此更新我的答案。
    • 感谢您的帮助!如果我要向 CumulativeBalance 表添加另一个名为 customerID 的字段,还有一个问题会更复杂。因此该表将保存许多客户的累积数据。当我下班回来时,我会仔细阅读古怪的更新和那些东西!谢谢。我想澄清一些事情,你说“实时数据,然后总是方法 1 将更适合 QUIRKY UPDATE”。我的方法 1 没有任何额外的表,我究竟在更新什么?谢谢!
    • 我建议制作不同的表格,以按客户 ID(CustomerIDSystemOpenDateCumulativeBalance)保持日期累计余额。
    • 对于方法 1,您没有使用任何表格。但如果你这样做,例如在我的解决方案中,临时表用于内部计算,我使用了古怪的更新。如果您不使用任何表意味着您正在通过直接选择进行输出,那么显然您不能使用它。我会建议为此使用窗口函数。我的意思是,通过窗口函数或奇特的更新运行总计总是比循环、光标、子查询或 CLR 提供更好的性能。
    猜你喜欢
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    相关资源
    最近更新 更多