存储数据库记录计数是多余的吗?

11
我正在使用Rails和MySQL,针对行计数有一个效率问题。
我有一个“Project”模型,其中包含“has_many:donations”。
我想要计算项目的独立捐赠人数。
在“projects”表中创建一个名为“num_donors”的字段,在创建新捐赠者时将其递增是一个好主意吗?
或者类似于“@num_donors = Donor.count(:select => 'DISTINCT user_id')”这样的语句是否会基于数据库优化而产生类似或相同的效果?这是否需要我为“user_id”和其他任何我想计数的字段创建索引?
对于总捐款金额的求和操作是否同样适用?
5个回答

21

回答标题问题。是的,它是多余的,但是否应该这样做取决于您的情况。

除非您已知有性能问题,在应用程序中根据需要动态计算计数和总数,并不要存储它们。也就是说,在没有其他选择的情况下,不要存储计算出来的值。

在大多数情况下,您不必采取这种方法,也不应该采取这种方法。

如果您必须存储计算出来的值,请执行以下操作:

  • 不要通过增量方式使其保持最新状态。每次更新时重新计算所有数据的计数/总数。
  • 如果更新不频繁,请将代码放入更新触发器中以使计数/总数保持最新。
  • 数据库中冗余的问题在于,当数字不一致时,您无法确定哪个是权威的。在文档中添加一条注释,说明源数据是权威来源,如果它们不一致,则可以进行覆盖。

+1 不要尝试进行增量/减量操作。如果计数存在一定的复杂性,这将为您节省麻烦。 - Matt Ramirez

10

虽然这取决于您的数据库大小,但这些都是数据库擅长的操作,因此它们应该很快。这可能是过度优化的情况 - 您应该先不存储总数,从而使其更简单 - 如果必要再进行优化。


8

记住这句话:“一个人只有一块手表,总是知道时间。有两块手表的人永远不确定时间。” 只有在以下情况下才会存储派生数字:

当性能问题阻止您在需要时获取派生数字时(在这种情况下,答案很可能可以从索引中获得,因此这不应该成为问题)

或者

您有理由相信通过程序员错误或故意或意外用户操作从主表中丢失了记录。在这种情况下,您可以使用派生数字来审计当前计算的数字。


2
喜欢这个格言 - 以前没听过。会记在心里的 :) - nfm
1
我喜欢这句话,它真的帮助了我。 - KimchiMan

5
Peter和JohnFx的答案很好,你提出的是数据库模式的去规范化denormalization,这可能会提高读取性能,但写入性能会受到影响,同时还需要开发人员(或额外的DBMS技术人员)防止数据集中的不一致。
ActiveRecord具有一些内置功能,可以自动管理has_many关系上的计数。查看这个Railscast on counter caches

3

你知道一个简单的flag就能实现ActiveRecord的魔法吗?

class ThingOwner

# it has a column like
# t.integer things_count, :default => 0

has_many :things, :counter_cache => true

end

关于这个问题 - 是的,如果things.count占用了太多时间,我会添加这样的计数器,否则这是过早的优化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接