我使用Rails和MySQL,并有基于行的计数的效率问题。
我有一个Project
是模型has_many :donations
。
我想算独特的供血者人数的一个项目。
是一种在一个领域projects
称为表num_donors
,并增加它,当一个新的捐助者创建一个好主意吗?
或者是像@num_donors = Donor.count(:select => 'DISTINCT user_id')
将是相似或数据库优化效率感谢的方面是相同的? 这是否会要求我创建索引user_id
和任何其他领域我想算什么?
不一样的答案保持总结捐赠的总额是多少?
要回答这个问题称号。 是的,它是多余的,但无论你应该做它取决于你的情况。
除非你已经知道的性能问题,计算出在你的程序运行中的数和总数,并且不保存。 也就是说,不,除非你有没有其他选择存储计算值。
在大多数情况下,你不会有诉诸该与不该。
如果您必须存储计算值,请执行以下操作:
- 不要通过递增它跟上最新的。 重新计算所有每次更新数据的计数/总。
- 如果你没有很多的更新,将代码放在一个更新触发器,以保持计数/总计最新的。
- 与数据库中的冗余麻烦的是,当数值不同,无法确定哪个是权威的。 添加到文档的说明源数据是权威的来源,如果他们不同意,可以覆盖。
虽然这取决于你的数据库的大小,这些都是种类的数据库专门的操作,所以他们应该是快速的。 这也可能是在这里过早优化的情况 - 你应该不存储总计开始,从而使其更简单 - 如果以后需要优化。
记住的格言“有一只表的人总是知道的时间。有两个手表的人是从来不肯定。” 我只会存储派生的号码,如果:
性能问题阻止你获得派生数字时,你需要他们(因为答案很可能是从指标不应是在这种情况下一个问题)
要么
你有理由相信,你是从主表通过编程错误或有意或无意用户操作失败的记录。 在这种情况下,您可以使用您的派生号审计当前计算的数字。
彼得和JohnFx的答案是健全的,你要提出的是反规范化数据库模式,它可以在写入的损害提高读取性能,但同时另外把责任推给开发商(或其他DBMS clevers),以防止内部矛盾的数据集。
ActiveRecord的有内建的功能来自动管理计数has_many
关系。 看看这个在柜台缓存Railscast 。
你知道,一个简单的标志确实ActiveRecord的魔力?
class ThingOwner
# it has a column like
# t.integer things_count, :default => 0
has_many :things, :counter_cache => true
end
至于这个问题-是的,当然它是多余的,我想补充这样一个计数器,当且仅当things.count
时间的份额过大。
否则,它过早的优化。