代码之家  ›  专栏  ›  技术社区  ›  anthares

尝试设计一个列,该列应与另一个表中的值求和

  •  1
  • anthares  · 技术社区  · 16 年前

    对不起,如果标题不太清楚。我现在试着解释一下:

    我有两张表:A表和B表。它们之间的关系是一对多(B表)。所以,这有点像掌握细节的情况。 我在表B中有一列“amount”,显然是十进制的,在表A中有一列“totalamount”。 我正在努力找出如何保持表A中的值是最新的。我的建议是在表A的基础上进行一个视图,使用聚合查询来计算表B中的金额。当然,使用适当的索引… 但是,我的队友建议每次我们从应用程序中更改表B中的内容时都更新表A中的值。 我想知道,这里最好的解决办法是什么?可能是第三种变体?

    澄清一下……我们希望此表是数据库中增长最快的表。表B的增长速度比表A快得多,表B中最频繁的操作是插入…几乎没有别的。将选择表A中最频繁的操作…但不仅如此。

    4 回复  |  直到 16 年前
        1
  •  1
  •   Oded    16 年前

    我看到许多选项:

    1. 在表B上使用insert触发器,并按照您的朋友的建议更新表A。这将使表B尽可能保持最新。
    2. 有一个计划的作业,每隔X分钟更新表A(X=任何对应用程序有意义的内容)。
    3. 更新表B时,在应用程序逻辑中对表A进行更新。如果您在许多地方更新表B,这可能无法解决。
        2
  •  1
  •   Aaron Digulla    16 年前

    如果在应用程序中只有一个位置可以将新行插入表B,那么最简单的解决方案是发送 UPDATE A set TotalAmount=TotalAmount + ? where ID = ? 并传递刚才插入到B中的值。请确保在事务中同时包装两个查询(插入和更新),以便两者都发生或不发生。

    如果这不简单,那么下一个选项就是数据库触发器。阅读数据库的文档如何创建它们。基本上,触发器是一小段代码,当数据库中发生某种情况时(在您的例子中,当有人在表B中插入数据时)会执行它。

    视图是另一个选项,但它可能会在选择期间导致性能问题,您会发现很难解决。请尝试使用“物化视图”或“计算列”(但在插入/删除列时,这可能会导致性能问题)。

        3
  •  1
  •   soulmerge    16 年前

    如果这个值将发生很大的变化,那么最好使用一个视图:它绝对是更安全的实现。但更好的方法是使用触发器(如果数据库支持触发器的话)。

    我猜你的朋友建议更新每次插入的值,因为他认为你经常需要这个值,这可能会导致每次重新计算值的速度变慢。如果是这样的话:

    • 您的数据库应该负责缓存,所以这可能不是问题。
    • 不过,如果是这样的话,您可以在以后的阶段添加该特性—这样您就可以确保应用程序可以正常工作,并且 许多的 调试该缓存列更容易。
        4
  •  0
  •   Andrew Aylett    16 年前

    我绝对建议使用触发器而不是应用程序逻辑,因为这样可以确保数据库保持值最新,而不是依赖于所有调用方。但是,从设计的角度来看,我会谨慎地将生成的数据存储在与未生成的数据相同的表中--我认为保持清晰的分离是很重要的,因此人们不会混淆应该维护的数据和将维护的数据。

    但是,一般来说,更喜欢视图而不是触发器——这样就不必担心维护值了。用于确定性能是否为问题的配置文件。在Postgres中,我相信您甚至可以对计算值创建一个索引,这样数据库就不必查看细节表了。

    第三种方法是定期重新计算,比触发器慢得多,可能比视图慢。它不适合你的使用,不管怎样,这是锦上添花。