因此,它就像我们的正常银行账户,我们有很多交易导致资金流入或流出。总是可以通过简单地总结交易价值来得出账户余额。在这种情况下,将更新的帐户余额存储在数据库中或在需要时重新计算它会更好吗?
每个帐户的预期交易量:<每天5次
帐户余额的预期检索:每当交易发生时,平均每天一次。
您如何建议对此做出决定? 非常感谢!
答案 0 :(得分:89)
前言
审计要求是会计系统的客观事实。此外,在处理公共资金时,必须遵守法律。
您不必实施完整的会计要求,您只需实施所需的部分即可。
相反,实施以外的标准会计要求(其中的部分)是不明智的,因为这可以保证当错误数量或负载超过某个阈值时,或者系统扩展,你将不得不重新实施。可以而且应该避免的成本。
还需要说明的是:不要聘请不合格,未经认可的审核员"。会有后果,就像你雇用一个不合格的开发人员一样。如果税务局罚款你可能会更糟。
不那么原始的国家的标准会计方法就是这样。 "最佳实践",如果你愿意的话,在其他人中。
此方法适用于具有类似操作的任何系统;需要;历史月度数据与当前月份要求,如库存控制等
首先,考虑因素。
永远不要复制数据。如果可以导出当前余额(这里很简单),请不要使用摘要列复制它。这样的列是数据的重复。它打破了规范化规则。此外,创建更新异常,否则不存在。
如果您使用摘要列,则每当更新事务时(如更改时,而不是插入新事务时),摘要列值将变得过时,因此它无论如何必须一直更新。这是Update Anomaly的结果。这消除了拥有它的价值。
外部出版物。如果余额发布,如每月的银行对账单,这些文件通常具有法律限制和含义,因此公布的CurrentBalance值在发布后不得更改。
在发布日期之后,在数据库中对外部发布的数字进行的任何更改都是不诚实行为,欺诈等的证据。
您不希望您的银行在2015年4月将您在银行对帐单中发布的当前余额更改为2014年12月。
该数字必须被视为审计数字,已发布且不可更改。
任何必要的更正或调整均作为当前月份的新交易进行,即使它适用于上个月。这是因为适用的月份已关闭并发布,因为在发生历史记录并且已记录之后,不能更改历史记录。唯一有效的月份是现在的月份。
对于生息系统等,在不那么原始的国家,当发现错误时,它会产生历史性影响(例如,您在2015年4月发现了对证券计算的利息)自2014年12月以来一直是错误的,修正后的利息支付/扣除的价值是今天计算的,对于错误的天数,该金额作为当前月份的交易插入。同样,唯一有效的月份是当前的月份。
当然,安全的利率也必须得到纠正,因此错误不会重复。
如果您发现银行计算您的储蓄(计息)帐户的利息时出现错误,并且您已将其更正,则会获得一笔存款,这构成了整个调整值,在本月。这是当月的交易。
银行没有:改变历史;申请每个历史月份的利息;回顾历史性的银行对账单;重新发布历史性的银行对账单。不可以。也许在Idi Amin类型的国家。
同样的原则适用于库存控制系统。它保持了理智。
所有真实的会计系统(即在适用的国家/地区通过审核机构认证的系统,而不是米老鼠"包装和#34;那些)都使用Double Entry系统进行交易正是因为它可以防止大量的错误,其中最重要的是,资金不会丢失"。这需要一个简单的总帐。
影响性能的主要问题超出了本问题的范围,它们是否是您实现真正的关系数据库(SQL数据库容器中的记录归档系统,以ID为代表) 。
使用真正的关系密钥等将保持高性能,无论表的填充程度如何。
相反,RFS表现不佳,根本无法执行。 "刻度"当在RFS的背景下使用时,是一个欺诈性的术语:它隐藏了原因并试图解决除原因之外的所有事情。
对于每个帐户,AccountStatement表中都会有一个ClosingBalance(每个帐户每月一行),以及StatementDate和其他Statement详细信息。
这不是重复的,因为它需要审计和健全的目的。
对于Inventory,一个QuantityOnHand列,在PartAudit表中(每个部件每月一行)
它有一个额外的值,因为它限制了当前月份所需查询的事务行的范围
同样,如果您的表是Relational,则AccountTransaction的主键将是(AccountCode,TransactionDateTime),它将以毫秒的速度检索事务。
对于记录归档系统,"主键"将是(TransactionID),您将通过TransactionDate检索当前月份,该月份可能正确索引或未正确索引,并且所需的行将分布在整个文件中。在任何情况下,远远低于ClusteredIndex速度,并且检索到的行数很多,表扫描。
交易表仍然很简单(银行账户交易的真实概念很简单)。它有一个正数量列。
对于每个帐户,CurrentBalance为:
上个月的Statement.ClosingBalance
(对于库存,PartAudit.QuantityOnHand)
加上当前月份的Transaction.Amounts总和,其中TransactionType表示存款
(对于库存,Transaction.QuantityAffected)
减去当前月份的Transaction.Amounts总和,其中TransactionType表示提款
在此方法中,仅当前月份的交易处于不稳定状态,因此必须派生。所有前几个月都已公布和关闭,因此必须>>审核数字。
可以清除Transaction表中的旧行。超过十年的公共资金,五年,否则,一年的业余爱好俱乐部系统。
当然,任何与会计系统相关的代码都必须使用正版的OLTP标准和真正的SQL ACID交易。
此设计包含所有范围级别的性能考虑因素(如果这不明显,请请求扩展)。扩展是一个非问题,现在扩展问题实际上是在数据库之外。
这些项目之所以需要说明,只是因为SO Answers中提供了错误的建议(当然是民主上的民众投票),互联网充满了不正确的建议(业余爱好者喜欢发布他们的主观的"真理"):
显然,有些人不明白我在技术方面给出了一个方法。因此,它不是特定国家/地区中特定应用程序的伪代码。该方法适用于有能力的开发人员,对于那些需要牵手的人来说,它还不够详细。
他们也不明白一个月的截止时间就是一个例子:如果税务局的截止时间是季度,那么一定要用季度截止时间;如果您拥有的唯一法律要求是年度,则使用年度。
即使您的外部或合规目的是季度截止,公司也可能选择每月截止,用于内部审计和理智目的(即保持国家时期的长度)将通量降至最低。)
EG。在澳大利亚,税务局对企业的停产季度,但较大的公司每月停止库存控制(这节省了长期追逐错误)。
EG。银行每月都有法律合规要求,因此他们会对数据进行内部审计,并每月关闭账目。
在原始国家和流氓国家,由于明显的邪恶目的,银行将其流通状态时期保持在最大值。其中一些人每年只会制作合规报告。这就是为什么澳大利亚银行不会倒闭的原因之一。
在“交易”表格中,不要在“金额”列中使用负数/正数。金钱总是有正值,没有负二十美元的东西(或者你欠我的钱减去五十美元,然后确定双重否定意味着别的东西)。
移动方向,或者您要对资金进行的操作,是一个独立且离散的事实(对于Transaction.Amount)。这需要一个单独的列(一个数据中的两个事实打破规范化规则,结果是它在代码中引入了复杂性)。
实施一个TransactionType列,即存款/取款的(D,W)作为起点。随着系统的增长,只需添加(A,R,W,M)进行调整,退款,ATM_Withdrawal,Management_Fee等。
无需更改代码。
在一些原始国家,诉讼要求规定,在任何列出交易的报告中,必须在每一行显示一个运行总计。 (注意,这不是审计要求,因为这些要求比法院要求更优越[上述方法];审计师比律师更愚蠢;等等。)
显然,我不会在法庭要求上提出异议。问题是原始编码器将其转换为:哦,我们必须实现 Transaction.CurrentBalance 列。他们不理解:
在报表上打印列的要求不是在数据库中存储值的要求
任何类型的运行总计都是派生值,并且很容易编码(如果对您来说不容易,请发一个问题)。只需在报告中实现所需的代码即可。
实施运行总计,例如。 Transaction.CurrentBalance作为列会导致可怕的问题:
引入了重复列,因为它是可派生的。打破规范化。介绍更新异常。
更新异常:每当历史插入事务或更改Transaction.Amount时,必须重新计算从该日期到当前的所有Transaction.CurrentBalances 更新
在上述情况下,提交法院使用的报告现已过时(每一份在线数据报告在打印时都已过时)。 IE浏览器。打印;评论;改变交易;重印;重新审视,直到你开心。无论如何,它毫无意义。
这就是为什么在不太原始的国家,法院不接受任何旧的印刷纸,他们只接受公布的数字,例如。银行对账单已经受审计要求的约束(参见上述方法),无法召回或更改并重新打印。
答案 1 :(得分:2)
这是相当主观的。我建议考虑的事项是:
就所提出的两种方法的优点而言,按需总结交易价值可能更容易/更快地实施方法。
但是,它不会扩展以及将当前帐户余额保持为数据库中的字段并随时更新。并且它会在一定程度上增加您的整个事务处理时间,因为每个事务都需要运行查询来计算当前帐户余额才能继续。在实践中,除非您在不久的将来拥有大量的账户/交易或期望,否则这些可能是一个小问题。
第二种方法的缺点是它可能需要花费更多的开发时间/精力来进行初始设置,并且可能需要您考虑如何在帐户内同步事务以确保每个人们可以随时准确地看到并更新余额。
因此,它主要归结为项目的需求,目前最好的开发时间,以及现在是否值得面向解决方案,而不是实施第二种方法后来,当性能和可扩展性成为现实而不是理论上的问题时。