例如,我有一个银行用户表(用户ID,用户名)和一个交易表(用户ID,帐户ID,金额)。
帐户在不同用户之间具有相同的属性,但持有不同的金额(例如Alex - > Grocery,它特定于Alex,但所有其他用户也有Grocery帐户)。
问题是,创建一个单独的帐户表(帐户ID,用户ID,剩余金额)或通过选择具有所需用户ID和帐户ID的所有交易来获取此值会更好吗?数量'价值?似乎第一种方法会更快,但更容易出错和数据库损坏 - 每次事务发生时我都需要更新帐户。第二种方法似乎更清洁,但它会导致显着的减速吗?
你会推荐什么?
答案 0 :(得分:3)
在我看来,你应该总是避免重复数据,所以我会在每次选择时使用“求和”
“似乎第一种方法会更快,但更容易出错和数据库损坏 - 每次交易发生时我都需要更新帐户”
说出一切,你可能会遇到错误,你必须建立一种机制来保持数据的最新状态。
不要忘记第一种方法只能选择更快。插入更新和删除会更慢,因为您必须更新第二个表。
答案 1 :(得分:2)
这是Denormalization的一个例子。
一般情况下,不鼓励非规范化,但也有一些例外 - 银行账户余额通常是一个例外。
因此,如果这是您的确切情况,我建议使用单独的帐户表解决方案 - 但如果您的记录远远少于银行通常的情况,那么我建议使用派生方法,代替。
答案 2 :(得分:2)
在某种程度上,这取决于。
对于“小”数据量,性能将很可能正常。 但随着数据量的增长,必须对所有事务进行SUM处理可能会使您开始注意到性能问题。
还要考虑数据访问/使用模式。在一个准备好的系统中,你“一次写入,准备好许多”,然后SUM方法在每次读取时都会达到性能 - 在这种情况下,在写入时执行一次性能命中可能是有意义的,以提高后续的读取性能。
如果你预计“大”数据量,我肯定会使用额外的表来保持高水平的总数。您需要确保在进行(货币)事务时更新它,在(sql server)事务中使其成为原子操作。
如果数据量较小,你可以在没有它的情况下离开......就个人而言,我可能仍然会走这条路,以简化阅读方案。
答案 3 :(得分:1)
只有在遇到重大性能问题时才采用非规范化方法(第一种解决方案)。由于您只使用适当的索引进行简单的SUM(或分组,然后求和),因此您的规范化解决方案将非常有效并且将更容易维护(如您所述)。
但是根据您的查询,使用非规范化解决方案是有意义的...例如,如果您的数据库是只读的(您定期从其他数据源加载数据并且不在以下位置进行插入/更新)所有或使它们真的很少),然后你可以用最简单的方式加载数据来进行查询......在这种情况下,非规范化的解决方案可能会更好。